setup()
setup() runs once when the sketch starts. It builds the entire user interface by creating DOM elements (divs and buttons), styling them with CSS properties through the .style() method, and connecting click handlers to game logic. This game separates the p5.js canvas (for drawing faces) from the p5.js DOM layer (for text and buttons), which is a powerful pattern for combining graphics and interactivity.
function setup() {
createCanvas(windowWidth, windowHeight);
background(220); // Initial canvas background
// Create main container for UI elements to center them
// Using p5.js DOM functions is crucial here, not raw document.createElement
// https://p5js.org/reference/#/p5/createDiv
const uiContainer = createDiv('');
uiContainer.style('display', 'flex');
uiContainer.style('flex-direction', 'column');
uiContainer.style('align-items', 'center');
uiContainer.style('justify-content', 'center');
uiContainer.style('position', 'absolute');
uiContainer.style('top', '0');
uiContainer.style('left', '0');
uiContainer.style('width', '100%');
uiContainer.style('height', '100%');
uiContainer.style('padding', '20px');
uiContainer.style('box-sizing', 'border-box'); // Include padding in element's total width and height
// Situation Display (text and drawing)
situationDisplay = createDiv('');
situationDisplay.style('font-size', '2em');
situationDisplay.style('margin-bottom', '30px');
situationDisplay.style('text-align', 'center');
situationDisplay.style('max-width', '800px'); // Limit width for readability
situationDisplay.parent(uiContainer); // Attach to the UI container
// Progress Indicator
progressIndicator = createDiv('');
progressIndicator.style('font-size', '1.2em');
progressIndicator.style('margin-bottom', '20px');
progressIndicator.parent(uiContainer);
// Buttons container
const buttonsContainer = createDiv('');
buttonsContainer.style('display', 'grid');
buttonsContainer.style('grid-template-columns', '1fr');
buttonsContainer.style('gap', '15px');
buttonsContainer.style('width', '100%');
buttonsContainer.style('max-width', '400px'); // Limit button width
buttonsContainer.parent(uiContainer);
// Multiple Choice Buttons
for (let i = 0; i < 3; i++) {
// https://p5js.org/reference/#/p5/createButton
const button = createButton('');
button.style('padding', '15px 25px');
button.style('font-size', '1.2em');
button.style('cursor', 'pointer');
button.style('border', 'none');
button.style('border-radius', '10px');
button.style('background-color', '#4CAF50'); // Green
button.style('color', 'white');
button.style('transition', 'background-color 0.3s ease');
button.mousePressed(() => checkAnswer(i)); // Use p5.js mousePressed
// Use p5.js style() method, not raw DOM style
button.mouseOver(() => button.style('background-color', '#45a049')); // Darker green on hover
button.mouseOut(() => button.style('background-color', '#4CAF50'));
button.parent(buttonsContainer);
optionButtons.push(button);
}
// Feedback Display
feedbackDisplay = createDiv('');
feedbackDisplay.style('font-size', '1.5em');
feedbackDisplay.style('margin-top', '20px');
feedbackDisplay.style('font-weight', 'bold');
feedbackDisplay.parent(uiContainer);
// Restart Button (hidden initially)
restartButton = createButton('Play Again');
restartButton.style('padding', '15px 25px');
restartButton.style('font-size', '1.2em');
restartButton.style('cursor', 'pointer');
restartButton.style('border', 'none');
restartButton.style('border-radius', '10px');
restartButton.style('background-color', '#008CBA'); // Blue
restartButton.style('color', 'white');
restartButton.style('transition', 'background-color 0.3s ease');
restartButton.mousePressed(restartGame);
restartButton.mouseOver(() => restartButton.style('background-color', '#007ba7'));
restartButton.mouseOut(() => restartButton.style('background-color', '#008CBA'));
restartButton.style('margin-top', '30px');
restartButton.hide(); // Hide initially
restartButton.parent(uiContainer);
displaySituation(currentSituationIndex);
}
Line-by-line explanation (6 lines)
🔧 Subcomponents:
uiContainer.style('display', 'flex');
Creates a centered column layout that vertically and horizontally aligns all game elements (situation, buttons, feedback) in the middle of the screen
for (let i = 0; i < 3; i++) {
Loops three times to create three answer option buttons and adds them to the optionButtons array so they can be updated later
createCanvas(windowWidth, windowHeight);- Creates a canvas that fills the entire browser window so the face animation and background are visible
const uiContainer = createDiv('');- Creates an empty p5.js DOM element (a div) that will hold all the game UI text and buttons so they can be styled and positioned together
uiContainer.style('display', 'flex');- Enables flexbox layout mode on the container so child elements (situation, buttons) can be centered and aligned vertically
for (let i = 0; i < 3; i++) {- Loops three times, creating one button for each of the three answer options
button.mousePressed(() => checkAnswer(i));- Attaches a click handler to each button that calls checkAnswer with the button's index (0, 1, or 2) so the game knows which option was chosen
displaySituation(currentSituationIndex);- Calls the displaySituation function to show the first game scenario and populate the buttons with the first three answer options