Game Design & Development · Tiny-Loop Tutorial · Archetype #7

Tutorial: Top-Down "Shooter"

Player Movement Projectiles Target Spawning Score & Win Pre-built Sprites

This is the exact Top-Down "Shooter" archetype from What Makes a Game? — already built and running below, kept nonviolent by design (pop balloons, zap viruses, spray out fires). Play it, then swap the pre-built sprites and pace using the panel underneath. You can't break the loop itself; that part is locked. Once you've tuned a version you like, you'll build this same architecture two more times: with Scratch's blocks, then from real scratch in JavaScript.

🗺️ The Architecture

Every tiny-loop game starts as a concept, then gets broken into a core loop, a systems list, and a structure — before anyone touches sprites or colors. Here's the Top-Down "Shooter"'s architecture:

🌱ConceptAim and fire at targets before time or patience runs out.
🔁Core LoopMove → fire a projectile → it travels → hits a target → target disappears, score +1.
🧩SystemsPlayer movement, projectile spawner, target spawner, hit detection.
🏁Win/LoseReach the score goal to win. There's no lose state — just accuracy and speed.

The four systems, in order of execution every frame:

  1. Input system — reads held arrow keys to move the player along the bottom, and a key press to fire.
  2. Projectile system — each fire press spawns one projectile at the player's position that travels straight up until it hits something or leaves the screen.
  3. Target spawner system — keeps a small number of targets alive at fixed slots near the top, respawning a new one wherever one just got hit.
  4. Hit detection system — checks every projectile against every target with AABB; on a hit, the target disappears, the projectile is removed, and the score increases.

🎮 Play & Customize

Move with Arrow keys, A / D, or touch buttons. Fire with Space, Arrow Up, click, or the touch Fire button. Clear enough targets to win.

Score: 0 A·D move · Space fires

💡 Click inside the game first — that gives it keyboard focus so A/D and Space control the game instead of scrolling the page.

Tune the Game (limited, on purpose)

Notice what you can't change here: there's no field for "how targets respawn" or "how hits are detected." That's the engine — the part every version of this game shares. You're only tuning content, not rewriting architecture. That's the limit, on purpose.

What Projectile Speed actually touches in the engine: it's only how many pixels each projectile's y shrinks by per frame once it's already in flight (p.y -= config.projectileSpeed) — it doesn't touch how often you can fire (there's no cooldown; one key press is one projectile) or how close a projectile has to be to register a hit in collides(). Same fire rate and hit radius at every speed.

👀 Peek at the Code

The game running above is this code — nothing hidden. It's split into two parts on purpose: a small config object you just edited with the panel, and a locked engine that reads it.

✏️ Config — this is what the panel above edits
const config = {
  theme:  'balloons',
  player: '🧑',
  projectileSpeed: 4,
  winScore: 15
};

👆 This block updates live — hit "Apply & Restart" above and watch the exact values change here. There's no separate "demo" version of the code; this is it.

🔒 Engine — locked, shared by every version of this game
function update() {
  // 1. move the player from held keys
  if (keys.left)  player.x -= 5;
  if (keys.right) player.x += 5;

  // 2. fire spawns one projectile that travels straight up
  if (firePressed) { projectiles.push({ x: player.x, y: player.y }); firePressed = false; }
  projectiles.forEach(p => p.y -= config.projectileSpeed);

  // 3. keep target slots filled
  targets.forEach(t => { if (!t.alive) respawn(t); });

  // 4. check every projectile against every target
  projectiles.forEach(p => targets.forEach(t => {
    if (t.alive && collides(p, t)) { t.alive = false; p.hit = true; score++; }
  }));
}
This is what "architecture" means in practice: the config is the part of the design doc you filled out in Lesson 1 (goal, mechanic, feedback). The engine is the part no one writes twice — the same movement, projectile, spawner, and hit-detection systems power every top-down target game, whatever the theme.

🛠️ Now Build It For Real

You've played a working target game and seen exactly how it's built. Next, build this same architecture yourself — twice, in two different tools.

🧩 Step 1 — Build It in Scratch

The "Build the Loop with Blocks" section above already shows the exact scripts — backdrop, sprites, variables, and all six scripts (using broadcasts to connect Player, Projectile, and Target), block by block, in Scratch's own category colors. Open a Scratch tab side-by-side and copy each script exactly; the game should come to life the same way it does here.

Open a blank Scratch project tab →

Want more practice first? Two official Scratch resources cover the pieces this loop is built from.

Step 2 — Code It From Real Scratch (Lesson 2) Write this same projectile system, target spawner, and hit detection yourself in plain JavaScript and HTML5 Canvas — no engine, no blocks. ↩️ Back to the Archetype Grid Return to What Makes a Game? to try another tiny-loop archetype or the design workshop.