Module 15

Run and Gun

Side-scrolling action with relentless firepower — never stop moving, never stop shooting.

"One more quarter, one more try."


Prerequisites

ModuleWhat You Used From It
Module 02 - PlatformerPlatformer movement, gravity, and collision — a run and gun is a platformer with weapons
Module 03 - Top-Down ShooterProjectile systems, enemy spawning, and hit detection, now in a side-scrolling context

Week 1: History & Design Theory

The Origin

Contra (1987), developed by Konami and directed by Shigeharu Umezaki, established the run and gun genre. It combined side-scrolling platforming with eight-directional shooting, one-hit-kill difficulty, and two-player simultaneous co-op. Its genius was in economy: the player could run, jump, and aim in any of eight directions, but a single enemy bullet meant death. This created a game where every second demanded spatial awareness, pattern recognition, and reflexes. The Konami Code became famous precisely because Contra was so punishing — 30 lives felt generous.

How the Genre Evolved

Metal Slug (SNK, 1996) elevated the genre through lavish hand-drawn animation, destructible environments, and vehicles the player could commandeer. It added weapon pickups with limited ammunition that encouraged constant cycling, and its hostage-rescue mechanic gave players a reason to explore.

Gunstar Heroes (Treasure, 1993) introduced a weapon combination system where the player could hold two weapon types and combine them for unique effects, adding strategic choice to a genre typically defined by reflex alone.

Cuphead (Studio MDHR, 2017) brought the genre to a new audience by pairing 1930s hand-drawn animation with punishing boss-rush gameplay. Its parry mechanic (slapping pink objects to build super meter) added a risk/reward layer that rewarded aggressive, precise play. Cuphead proved that the boss fight — the genre's climactic moments — could sustain an entire game.

What Makes Run and Gun Great

The core design insight of the run and gun genre is authored tension. Unlike genres where difficulty emerges from systems, a run and gun game is a choreographed experience — every enemy placement, every platform, every boss attack is hand-designed to create a specific moment of pressure. The designer controls exactly when the player will face three enemies from the left while jumping a pit. This authorship means the game can escalate difficulty with precision, creating a rhythm of tension and release that feels almost musical. The player's mastery is not over a system but over a performance — memorizing the choreography until execution becomes fluid.

The Essential Mechanic

Simultaneous movement and shooting through authored encounter spaces — the player must navigate platforming challenges while aiming and firing at enemies placed to create specific pressure moments.


Week 2: Build the MVP

What You're Building

A single side-scrolling level with enemy encounters that the player must shoot through, ending with a multi-phase boss fight. The player can move, jump, and aim in at least 4 directions while firing. Include at least one weapon pickup and a lives system.

Core Concepts (Must Implement)

1. Multi-Directional Aiming While Moving

The player character must be able to aim in multiple directions (at minimum: forward, up, diagonal-up-forward, diagonal-down-forward) while running and jumping. Aiming direction and movement direction are controlled independently.

# Aim direction based on input
def get_aim_direction(input):
    aim_x = 0
    aim_y = 0

    if input.aim_up:
        aim_y = -1
    if input.aim_down:
        aim_y = 1

    if not input.aim_up or not input.aim_down:
        aim_x = player.facing_direction  # -1 or 1

    if input.aim_up and not input.move_left and not input.move_right:
        aim_x = 0

    return normalize(aim_x, aim_y)

def fire_bullet(player, aim_dir):
    bullet = Bullet(
        x = player.x + aim_dir.x * GUN_OFFSET,
        y = player.y + aim_dir.y * GUN_OFFSET,
        vx = aim_dir.x * BULLET_SPEED,
        vy = aim_dir.y * BULLET_SPEED
    )
    bullets.append(bullet)

Why it matters: Multi-directional aiming is what separates a run and gun from a platformer that happens to shoot. The ability to aim independently of movement creates the core skill expression — managing two degrees of freedom simultaneously under pressure.

Interactive: Multi-Directional Aiming

Use arrow keys to aim in 8 directions (including diagonals). The character stays centered. An aim line shows the current direction. Press Space to fire a projectile. The character sprite reflects the aim direction.

2. Scrolling Level Design with Enemy Placement

The level scrolls horizontally as the player advances. Enemies are placed at authored positions and activate when they scroll into view.

level_data = {
  segments: [
    {
      start_x: 0, end_x: 800,
      platforms: [ { x: 200, y: 300, w: 100, h: 20 }, ... ],
      enemies: [
        { type: "soldier", x: 400, y: 380, trigger_x: 200,
          behavior: "run_and_shoot" },
        { type: "turret", x: 700, y: 200, trigger_x: 500,
          behavior: "aim_at_player" },
      ]
    }
  ]
}

camera_x = clamp(player.x - SCREEN_WIDTH / 2, 0, LEVEL_WIDTH - SCREEN_WIDTH)

for enemy in inactive_enemies:
    if player.x >= enemy.trigger_x:
        enemy.active = true

Why it matters: Authored enemy placement is the authorial voice of the genre. Each encounter is a hand-crafted challenge. The trigger system ensures enemies appear at the right moment.

3. Boss Pattern Design

The end-of-level boss uses a multi-phase state machine with telegraphed attacks and vulnerability windows. Each phase has distinct attack patterns.

class Boss:
    def __init__(self):
        self.health = 100
        self.phase = 1
        self.state = "idle"
        self.state_timer = 0
        self.vulnerable = false

    def update(self, dt):
        self.state_timer -= dt

        if self.health <= 60 and self.phase == 1:
            self.phase = 2
            self.enter_state("phase_transition")
        if self.health <= 25 and self.phase == 2:
            self.phase = 3
            self.enter_state("phase_transition")

        if self.state == "telegraph_attack":
            if self.state_timer <= 0:
                self.enter_state("attack")
        elif self.state == "attack":
            self.execute_attack(self.phase)
            if self.state_timer <= 0:
                self.enter_state("vulnerable")
        elif self.state == "vulnerable":
            self.vulnerable = true
            if self.state_timer <= 0:
                self.vulnerable = false
                self.enter_state("telegraph_attack")

Why it matters: Boss fights are the genre's defining moments. The telegraph-attack-vulnerability loop is the fundamental rhythm that lets players learn a boss through observation and repetition.

Interactive: Boss Pattern Visualizer

A boss on the right cycles through phases: Idle (gray), Telegraph (yellow flash), Attack (red), and Vulnerable (green). The timeline bar at the bottom shows the current phase. Click "Attack" during the green Vulnerable window to deal damage. The boss has 3 health phases.

4. Co-op / Two-Player Simultaneous Play

Two players share the same screen, each controlling an independent character. The camera must accommodate both players.

players = [Player(id=0), Player(id=1)]

input_maps = {
    0: { "left": KEY_A, "right": KEY_D, "up": KEY_W, "jump": KEY_SPACE,
         "fire": KEY_F },
    1: { "left": KEY_LEFT, "right": KEY_RIGHT, "up": KEY_UP,
         "jump": KEY_RCTRL, "fire": KEY_RSHIFT }
}

def update_camera():
    lead_x = max(p.x for p in players if p.alive)
    camera_x = clamp(lead_x - SCREEN_WIDTH * 0.4, 0, LEVEL_WIDTH - SCREEN_WIDTH)

Why it matters: Co-op transforms the experience from a solo test of skill into a shared spectacle. It introduces genuine design challenges: the camera must serve two players, and difficulty must scale.

5. Limited Lives / Continue System

Each player starts with a fixed number of lives. Dying costs one life and respawns the player.

class LifeSystem:
    def __init__(self, starting_lives=3, max_continues=3):
        self.lives = starting_lives
        self.continues = max_continues

    def on_death(self, player):
        self.lives -= 1
        if self.lives > 0:
            player.respawn(delay=1.5)
            return "respawn"
        elif self.continues > 0:
            return "continue_prompt"
        else:
            return "game_over"

Why it matters: The lives system creates stakes. Too punishing drives players away; too lenient removes tension. The continue system balances these forces.

6. Weapon Switching / Power-Up Cycling

The player can pick up weapon power-ups that replace or augment their default gun. Each weapon has distinct characteristics.

WEAPONS = {
    "default":      { fire_rate: 0.15, damage: 1, pattern: "single" },
    "spread":       { fire_rate: 0.25, damage: 1, pattern: "fan_5" },
    "laser":        { fire_rate: 0.05, damage: 0.5, pattern: "continuous" },
    "missile":      { fire_rate: 0.6, damage: 5, pattern: "single_explosive" },
}

def fire_weapon(player, aim_dir):
    weapon = WEAPONS[player.current_weapon]
    if player.fire_cooldown > 0:
        return
    player.fire_cooldown = weapon.fire_rate

    if weapon.pattern == "single":
        spawn_bullet(player.pos, aim_dir, weapon.damage)
    elif weapon.pattern == "fan_5":
        for angle_offset in [-30, -15, 0, 15, 30]:
            rotated = rotate_vector(aim_dir, angle_offset)
            spawn_bullet(player.pos, rotated, weapon.damage)

Why it matters: Weapon variety gives the player tactical choices within the moment-to-moment action. Different weapons excel against different enemy configurations.


Stretch Goals

MVP Spec

FeatureRequired
Player movement with platforming (run, jump)Yes
Multi-directional aiming (4+ directions)Yes
Firing projectiles in aim directionYes
Scrolling level with authored enemy placementsYes
At least 3 enemy types with distinct behaviorsYes
Multi-phase boss at level endYes
Boss telegraph and vulnerability windowsYes
Two-player co-op on shared screenYes
Lives system with respawnYes
At least 2 weapon pickupsYes
Vehicle sectionStretch
Screen-clearing bombStretch
Score / ranking systemStretch
Destructible environmentStretch

Deliverable

Submit your playable run and gun level with source code, including the boss fight. Include a short write-up (300-500 words) answering: How did you design your boss's phases to teach the player its patterns? Describe the telegraph-attack-vulnerability loop for each phase and how difficulty escalates between phases.


Analogies by Background

These analogies map game dev concepts to patterns you already know. Find your background below.

For Backend Developers

ConceptAnalogy
Multi-directional aimingA request router resolving two independent parameters simultaneously (resource path + HTTP method)
Scrolling level with enemy placementA queue-based job system — work items are pre-authored and activate when they reach the processing window
Boss pattern designA circuit breaker with states — closed (attacking), open (vulnerable), half-open (telegraph)
Co-op / two-playerMulti-tenant architecture — two independent users sharing the same runtime
Limited lives / continue systemRetry policies with exponential backoff — fixed retries before requiring manual intervention
Weapon switching / power-upsStrategy pattern — swapping the active algorithm at runtime based on configuration

For Frontend Developers

ConceptAnalogy
Multi-directional aimingA drag-and-drop handler tracking cursor position and modifier keys independently
Scrolling level with enemy placementVirtualized list rendering — elements activate when they scroll into the viewport
Boss pattern designA multi-step animation sequence — keyframes with transitions between states
Co-op / two-playerSplit state management — two independent component trees sharing a single layout container
Limited lives / continue systemForm validation retry limits — fixed attempts before locking the form
Weapon switching / power-upsTheme switching — swapping a configuration object that changes behavior and appearance

For Data / ML Engineers

ConceptAnalogy
Multi-directional aimingMulti-objective optimization — simultaneously optimizing two independent axes
Scrolling level with enemy placementWindowed stream processing — events are pre-positioned and activate when they enter the window
Boss pattern designA state machine in a Markov chain — defined transition probabilities between states
Co-op / two-playerMulti-agent simulation — two independent agents in a shared environment
Limited lives / continue systemTraining budget — a fixed compute allocation (lives) before the run terminates
Weapon switching / power-upsHyperparameter swapping mid-run — changing configuration during training

Discussion Questions

  1. Authored vs. emergent difficulty: Run and gun games hand-place every enemy encounter, while roguelikes procedurally generate them. What are the advantages and disadvantages of each approach?
  2. The camera problem in co-op: When two players share a screen but can move independently, the camera must make compromises. What happens when one player rushes ahead?
  3. Fairness in one-hit-kill design: Classic run and gun games kill the player in one hit, yet players accept this. What design elements make one-hit kills feel fair rather than frustrating?
  4. Boss readability: A boss with three phases needs to teach the player its patterns without explicit tutorials. How do you use visual and audio telegraphs?