Skip to content
Game 14 Unit 5 of 32 1 hr learning time

One Bullet Rule

Only one bullet on screen at a time — managing a single-instance constraint.

16% of Blockstorm

In the previous unit, pressing SPACE fires a bullet every time. If the player holds the key, bullets stream upward continuously. That makes the game too easy — and it creates drawing problems when multiple bullets overlap. The classic solution is the one-bullet rule: only one bullet can exist on screen at a time. Press SPACE again while a bullet is active and nothing happens. Wait for it to reach the top or hit something, then fire again.

The Program

5 REM === ONE BULLET RULE ===
10 BORDER 0: PAPER 0: INK 7: CLS
20 REM Define UDG I: player ship
30 FOR i = 0 TO 7
40 READ a
50 POKE USR "I" + i, a
60 NEXT i
70 DATA 16, 56, 56, 124, 254, 254, 130, 0
80 REM Define UDG E: bullet
90 FOR i = 0 TO 7
100 READ a
110 POKE USR "E" + i, a
120 NEXT i
130 DATA 16, 56, 16, 16, 0, 0, 0, 0
140 LET px = 15: LET py = 20
150 LET bx = 0: LET by = 0: LET ba = 0
155 PRINT AT 0, 0; INK 7; BRIGHT 1; "O/P=move SPACE=fire"
160 PRINT AT py, px; INK 7; CHR$ 152
170 REM === game loop ===
180 LET k$ = INKEY$
190 IF k$ = "o" OR k$ = "O" THEN IF px > 1 THEN PRINT AT py, px; " ": LET px = px - 1: PRINT AT py, px; INK 7; CHR$ 152
200 IF k$ = "p" OR k$ = "P" THEN IF px < 30 THEN PRINT AT py, px; " ": LET px = px + 1: PRINT AT py, px; INK 7; CHR$ 152
210 IF k$ = " " THEN IF ba = 0 THEN LET bx = px: LET by = py - 1: LET ba = 1: PRINT AT by, bx; INK 7; CHR$ 148
220 IF ba = 0 THEN GO TO 170
230 PRINT AT by, bx; " "
240 LET by = by - 1
250 IF by < 1 THEN LET ba = 0: GO TO 170
260 PRINT AT by, bx; INK 7; CHR$ 148
270 GO TO 170

How It Works

Variable d tracks whether the bullet is active. When d is 0, no bullet exists and the player can fire. When d is 1, a bullet is on screen and pressing SPACE does nothing.

The fire routine checks d before creating a bullet. If d is already 1, the routine returns immediately. If d is 0, it sets the bullet position to one row above the ship, sets d to 1, and draws the bullet UDG.

The bullet movement routine clears the bullet when it reaches the top of the screen by setting d back to 0. The next press of SPACE will fire again.

Why One Bullet?

The one-bullet rule is a game design choice, not just a technical limitation. It creates rhythm. The player fires, watches the bullet travel, waits for it to hit or miss, then fires again. Timing matters. Aim matters. Without the constraint, the player can spray bullets and hit everything without thinking.

Classic arcade games used this rule for the same reasons. Space Invaders allows one bullet on screen. Galaxian allows one. The constraint forces the player to be deliberate with every shot.

The Active Flag Pattern

The d variable is a simple boolean: 0 or 1. This pattern appears throughout game programming:

  • Is the bullet active? d = 1
  • Is the player alive? a = 1
  • Is the power-up collected? p = 1

A single variable controls whether something exists and whether the code that moves, draws or checks it should run at all. Every moving object in Blockstorm will use an active flag.

Try This

Count the misses. Add a variable that increments every time a bullet reaches the top of the screen without hitting anything. Display it on screen. How does seeing your miss count change how you play?

Two bullets. Allow two bullets on screen simultaneously by using two sets of position variables and two active flags. This previews the double-shot power-up that arrives later in the game.