Tutorials › Build a Game JS Mode

Build a Game

Put everything together and build a simple catching game from scratch, step by step!

1

The Player

Every game needs a player! Let's start with a paddle at the bottom of the screen that follows the mouse. We'll use constrain() to keep it inside the canvas.
0 / 13 lines
Loading editor...
size(400, 400); } function draw() { background("midnightblue"); // Player paddle let px = constrain(mouseX, 30, width - 30); fill("dodgerblue"); noStroke(); rect(px - 30, 370, 60, 15); }
2

A Falling Object

Now let's add something to catch! We'll create a ball that falls from the top. When it goes off the bottom, we'll reset it to the top at a random position.
0 / 28 lines
Loading editor...
let ballSpeed = 3; function setup() { size(400, 400); } function draw() { background("midnightblue"); // Falling ball fill("gold"); noStroke(); circle(ballX, ballY, 12); ballY += ballSpeed; // Reset when off screen if (ballY > height + 12) { ballY = -12; ballX = random(20, width - 20); } // Player paddle let px = constrain(mouseX, 30, width - 30); fill("dodgerblue"); rect(px - 30, 370, 60, 15); }
3

Collision Detection

The core of any game: checking if things are touching! We use dist() to measure the distance between the ball and the paddle center. If the ball is close enough, it's a catch!
0 / 42 lines
Loading editor...
let ballSpeed = 3; let score = 0; function setup() { size(400, 400); } function draw() { background("midnightblue"); // Falling ball fill("gold"); noStroke(); circle(ballX, ballY, 12); ballY += ballSpeed; // Player paddle let px = constrain(mouseX, 30, width - 30); fill("dodgerblue"); rect(px - 30, 370, 60, 15); // Collision check if (ballY > 360 && ballY < 385 && ballX > px - 35 && ballX < px + 35) { score++; ballY = -12; ballX = random(20, width - 20); } // Reset if missed if (ballY > height + 12) { ballY = -12; ballX = random(20, width - 20); } // Score fill("white"); textSize(20); text("Score: " + score, 10, 25); }
4

Lives and Game Over

Let's add consequences! The player starts with 3 lives. Missing a ball loses a life. When lives hit zero, the game is over and a message shows up. Press Space to restart!
0 / 72 lines
Loading editor...
let ballSpeed = 3; let score = 0; let lives = 3; let gameOver = false; function setup() { size(400, 400); resetBall(); } function resetBall() { ballY = -12; ballX = random(20, width - 20); } function draw() { background("midnightblue"); if (gameOver) { fill("white"); textSize(36); text("GAME OVER", 90, 150); textSize(20); text("Score: " + score, 150, 200); text("Press SPACE to restart", 80, 250); return; } // Falling ball fill("gold"); noStroke(); circle(ballX, ballY, 12); ballY += ballSpeed; // Player paddle let px = constrain(mouseX, 30, width - 30); fill("dodgerblue"); rect(px - 30, 370, 60, 15); // Catch! if (ballY > 360 && ballY < 385 && ballX > px - 35 && ballX < px + 35) { score++; resetBall(); } // Miss! if (ballY > height + 12) { lives--; if (lives <= 0) { gameOver = true; } resetBall(); } // HUD fill("white"); textSize(18); text("Score: " + score, 10, 25); text("Lives: " + lives, width - 90, 25); } function keyPressed() { if (key === " " && gameOver) { score = 0; lives = 3; ballSpeed = 3; gameOver = false; resetBall(); } }
5

Polish: Speed & Stars

Let's make it feel like a real game! We'll increase the speed as the score goes up, add some background stars for atmosphere, and show the level. This is the finished game!
0 / 84 lines
Loading editor...
let ballSpeed = 3; let score = 0; let lives = 3; let gameOver = false; let stars = []; function setup() { size(400, 400); resetBall(); for (let i = 0; i < 50; i++) { stars.push({ x: random(400), y: random(400), s: random(1, 3) }); } } function resetBall() { ballY = -12; ballX = random(20, width - 20); } function draw() { background("midnightblue"); // Stars noStroke(); fill("white"); for (let i = 0; i < stars.length; i++) { circle(stars[i].x, stars[i].y, stars[i].s); } if (gameOver) { fill("white"); textSize(36); text("GAME OVER", 90, 150); textSize(20); text("Final Score: " + score, 130, 200); text("Press SPACE to play again", 70, 250); return; } // Ball fill("gold"); noStroke(); circle(ballX, ballY, 12); ballY += ballSpeed; // Paddle let px = constrain(mouseX, 30, width - 30); fill("dodgerblue"); rect(px - 30, 370, 60, 15); // Catch if (ballY > 360 && ballY < 385 && ballX > px - 35 && ballX < px + 35) { score++; ballSpeed = 3 + score * 0.3; resetBall(); } // Miss if (ballY > height + 12) { lives--; if (lives <= 0) gameOver = true; resetBall(); } // HUD fill("white"); textSize(18); text("Score: " + score, 10, 25); text("Lives: " + lives, width - 90, 25); let level = Math.floor(score / 5) + 1; text("Level: " + level, width / 2 - 30, 25); } function keyPressed() { if (key === " " && gameOver) { score = 0; lives = 3; ballSpeed = 3; gameOver = false; resetBall(); } }

What to try next

  • Add multiple falling balls at once using an array
  • Add power-ups that make the paddle wider or give extra lives
  • Make some balls dangerous (red) — catching them loses a life
  • Add a high score that persists between game overs
  • Add sound effects — try playSound("coin") when you catch something!