Run and Gun
Side-scrolling action with relentless firepower — never stop moving, never stop shooting.
"One more quarter, one more try."
Prerequisites
| Module | What You Used From It |
|---|---|
| Module 02 - Platformer | Platformer movement, gravity, and collision — a run and gun is a platformer with weapons |
| Module 03 - Top-Down Shooter | Projectile 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.
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.
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
- Vehicle section: A brief segment where the player rides a vehicle with different movement and firepower.
- Screen-clearing bomb: A limited-use "smart bomb" that destroys all on-screen enemies and bullets.
- Score and ranking system: Track kills, accuracy, time, and deaths to assign a letter grade at level end.
- Destructible environment: Certain terrain elements can be destroyed by gunfire.
MVP Spec
| Feature | Required |
|---|---|
| Player movement with platforming (run, jump) | Yes |
| Multi-directional aiming (4+ directions) | Yes |
| Firing projectiles in aim direction | Yes |
| Scrolling level with authored enemy placements | Yes |
| At least 3 enemy types with distinct behaviors | Yes |
| Multi-phase boss at level end | Yes |
| Boss telegraph and vulnerability windows | Yes |
| Two-player co-op on shared screen | Yes |
| Lives system with respawn | Yes |
| At least 2 weapon pickups | Yes |
| Vehicle section | Stretch |
| Screen-clearing bomb | Stretch |
| Score / ranking system | Stretch |
| Destructible environment | Stretch |
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
| Concept | Analogy |
|---|---|
| Multi-directional aiming | A request router resolving two independent parameters simultaneously (resource path + HTTP method) |
| Scrolling level with enemy placement | A queue-based job system — work items are pre-authored and activate when they reach the processing window |
| Boss pattern design | A circuit breaker with states — closed (attacking), open (vulnerable), half-open (telegraph) |
| Co-op / two-player | Multi-tenant architecture — two independent users sharing the same runtime |
| Limited lives / continue system | Retry policies with exponential backoff — fixed retries before requiring manual intervention |
| Weapon switching / power-ups | Strategy pattern — swapping the active algorithm at runtime based on configuration |
For Frontend Developers
| Concept | Analogy |
|---|---|
| Multi-directional aiming | A drag-and-drop handler tracking cursor position and modifier keys independently |
| Scrolling level with enemy placement | Virtualized list rendering — elements activate when they scroll into the viewport |
| Boss pattern design | A multi-step animation sequence — keyframes with transitions between states |
| Co-op / two-player | Split state management — two independent component trees sharing a single layout container |
| Limited lives / continue system | Form validation retry limits — fixed attempts before locking the form |
| Weapon switching / power-ups | Theme switching — swapping a configuration object that changes behavior and appearance |
For Data / ML Engineers
| Concept | Analogy |
|---|---|
| Multi-directional aiming | Multi-objective optimization — simultaneously optimizing two independent axes |
| Scrolling level with enemy placement | Windowed stream processing — events are pre-positioned and activate when they enter the window |
| Boss pattern design | A state machine in a Markov chain — defined transition probabilities between states |
| Co-op / two-player | Multi-agent simulation — two independent agents in a shared environment |
| Limited lives / continue system | Training budget — a fixed compute allocation (lives) before the run terminates |
| Weapon switching / power-ups | Hyperparameter swapping mid-run — changing configuration during training |
Discussion Questions
- 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?
- 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?
- 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?
- 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?