Stage 1 — HTML Structure and Canvas Setup
In Stage 1 you write the HTML that frames the entire game and the opening lines of JavaScript that give the game a name and a home. By the end of this stage you will have a dark canvas visible in the browser — empty, but ready.
What you will build
Section titled “What you will build”index.html— the complete HTML structure for the game- The opening stub of
pop.js— thePOPnamespace object with a wired-upinit()method
Checkpoint: open index.html in a browser — you should see a dark blue-to-purple gradient canvas with a Start screen overlay.
Step 1 — Create the files
Section titled “Step 1 — Create the files”Create a project folder and add three empty files:
bubble-pop/├── index.html├── style.css└── pop.jsStep 2 — Write index.html
Section titled “Step 2 — Write index.html”The HTML has four jobs:
- Set up the document and load the stylesheet and script
- Provide the
<canvas>where all game graphics are drawn - Add a HUD (heads-up display) showing score, level, and lives
- Add two overlay screens — start and game over — that sit on top of the canvas
Open index.html and write:
<!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Bubble Pop</title> <link rel="icon" href="favicon.svg" type="image/svg+xml" /> <link rel="stylesheet" href="style.css" /> </head> <body> <div id="game-container"> <canvas id="game-canvas"></canvas>
<div id="hud"> <span id="score-display">Score: 0</span> <span id="level-display">Level: 1</span> <span id="lives-display">Lives: 3</span> </div>
<div id="start-screen" class="screen"> <h1>Bubble Pop</h1> <p id="high-score-display">Best: 0</p> <p class="instructions">Click or tap bubbles before they escape!</p> <button id="start-btn" type="button">Play</button> </div>
<div id="gameover-screen" class="screen hidden"> <h2>Game Over</h2> <p id="final-score">Score: 0</p> <p id="new-high-score" class="hidden">New High Score!</p> <button id="restart-btn" type="button">Play Again</button> </div> </div>
<script src="pop.js"></script> </body></html>Why this structure
Section titled “Why this structure”<canvas id="game-canvas">— the rendering surface. The JS will set its pixel dimensions; CSS controls how it is sized on screen.#hud— sits on top of the canvas via absolute positioning. Updated by JS every time the score or lives change.#start-screen/#gameover-screen— both have classscreen. The game-over screen also starts with classhidden. The JS adds and removeshiddento switch between them.<script>at the bottom — the script loads after the DOM is fully parsed, sodocument.getElementByIdcalls in JS will find the elements immediately.
Step 3 — Stub out pop.js
Section titled “Step 3 — Stub out pop.js”Before writing any game logic, establish the POP namespace object. A namespace object keeps all game variables and functions in one place and avoids polluting the global scope.
Open pop.js and write:
const POP = { // Config will go here in Stage 3 config: {},
// State state: 'start',
// DOM refs canvas: null, ctx: null,
init() { this.canvas = document.getElementById('game-canvas'); this.ctx = this.canvas.getContext('2d');
// Set the canvas pixel dimensions this.canvas.width = 480; this.canvas.height = 640;
console.log('POP initialized'); },};
document.addEventListener('DOMContentLoaded', () => POP.init());Key ideas
Section titled “Key ideas”const POP = { ... }— a plain object used as a namespace. All game state and methods live inside it.this.canvas.getContext('2d')— returns the Canvas 2D rendering context. Every drawing call (fillRect,arc,createRadialGradient, etc.) goes through this object.- Pixel dimensions vs. CSS dimensions —
canvas.widthandcanvas.heightset the internal pixel grid. CSSwidth: 100%stretches the canvas visually. You will handle the scaling mismatch in Stage 4 when you implement click detection. DOMContentLoaded— fires when the HTML is fully parsed. WrappingPOP.init()here ensures all thegetElementByIdcalls succeed even if the script is moved to the<head>later.
Checkpoint
Section titled “Checkpoint”Open index.html in a browser. The CSS you will write in Stage 2 does not exist yet, so the layout will be unstyled — you should still see the canvas element and the start screen text in plain browser defaults.
Check the browser console (F12 → Console) for the POP initialized message. If it appears, the DOM wiring is working.
Troubleshooting:
- No message in the console? Check that
<script src="pop.js">is at the bottom of<body>and that the filename matches exactly. getContext is not a function? Thecanvasvariable isnull, which meansgetElementById('game-canvas')did not find the element. Check thatid="game-canvas"is present in the HTML.
What’s next
Section titled “What’s next”In Stage 2 you will write all the CSS — the dark gradient canvas, the HUD positioning, the overlay screens, and the buttons.