Creative Coding · Session c14
Build a Mini-game
Firefly Rescue — plan it, build it in slices, then make it yours.
A finished game can look like one enormous problem. Programmers make it manageable by building one working slice at a time. Today your job is not to type the final code perfectly. It is to keep the program playable after every stage.
The blueprint
PlayerA lantern follows your pointer.
GoalRescue 10 moving fireflies.
PressureYou have 20 seconds.
Statesplaying → won or lost → restart.
Play the finished version
Move the lantern over each firefly. Tap after winning or losing to restart.
Stage 1 · Make one playable loop
Draw the lantern and one firefly. Move the lantern with the pointer. Do not add a timer yet. Test movement before going on.
Stage 2 · Turn one into many
Store fireflies in an array. Loop through them to move and draw. Rescue one with the c13 distance test.
Stage 3 · Add a beginning and endings
Add gameState and a timer. Only update objects while playing. Change to
'won' at 10 rescues or
'lost' when time reaches zero.
let flies = [];
let rescued = 0;
let gameState = 'playing';
let startedAt;
function setup() {
createCanvas(420, 280);
startGame();
}
function startGame() {
flies = [];
rescued = 0;
gameState = 'playing';
startedAt = millis();
for (let i = 0; i < 10; i++) addFly();
}
function addFly() {
flies.push({
x: random(20, width - 20),
y: random(55, height - 20),
vx: random(-1.2, 1.2),
vy: random(-1.2, 1.2)
});
}
function draw() {
background(10, 18, 35);
let secondsLeft = max(0, 20 - floor((millis() - startedAt) / 1000));
if (gameState == 'playing') {
updateFlies();
if (rescued == 10) gameState = 'won';
else if (secondsLeft == 0) gameState = 'lost';
}
drawLantern(mouseX, mouseY);
fill(255);
text('Rescued: ' + rescued + '/10 Time: ' + secondsLeft, 14, 25);
if (gameState == 'won') text('All safe! Tap to replay', 110, 145);
if (gameState == 'lost') text('Time! Tap to retry', 120, 145);
}
function updateFlies() {
for (let i = flies.length - 1; i >= 0; i--) {
let f = flies[i];
f.x += f.vx;
f.y += f.vy;
if (f.x < 10 || f.x > width - 10) f.vx *= -1;
if (f.y < 45 || f.y > height - 10) f.vy *= -1;
fill(220, 255, 150);
circle(f.x, f.y, 10);
if (dist(mouseX, mouseY, f.x, f.y) < 27) {
flies.splice(i, 1);
rescued += 1;
}
}
}
function drawLantern(x, y) {
noStroke();
fill(255, 220, 90, 55); circle(x, y, 52);
fill(255, 235, 130); circle(x, y, 18);
}
function mousePressed() {
if (gameState != 'playing') startGame();
}
Test after every stage. If a new feature breaks the game, the bug is probably in the few lines you just added. That is much easier to investigate than 80 new lines added at once. Use c11: read, print, isolate, check, explain.
Make this game unmistakably yours
- Balance: play three times. Adjust the time, speed, or collision distance until winning is possible but not automatic.
- Feedback: make a rescued firefly flash or leave a fading sparkle. The player should instantly know a collision happened.
- Choice: add a rare blue firefly worth 3 rescues, but make it move faster.
- State: add a
'start' screen so the timer begins only after the first tap.
- Original design: replace the theme, player, goal, and pressure. Keep the same program skeleton, but create a game no one else would make.
Next session → c15: Data & Charts
Your game keeps lists of things. Next you will use a list of numbers to draw a chart, and learn map(), the tool that turns data into pixels.