Movement and Firing
O/P keys move the ship, SPACE fires a bullet that moves upward — the erase-redraw pattern.
A static ship is not a game. This unit adds keyboard input and the erase-redraw pattern that makes movement work. O moves left, P moves right, and SPACE fires a bullet that travels upward from the ship. The bullet is a UDG character that moves one row per game tick, leaving a trail of cleared spaces behind it.
The Program
5 REM === MOVEMENT AND FIRING ===
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
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$ = " " AND ba = 0 THEN LET bx = px: LET by = py - 1: LET ba = 1: PRINT AT by, bx; INK 7; CHR$ 148
220 IF ba = 1 THEN PRINT AT by, bx; " ": LET by = by - 1: IF by < 1 THEN LET ba = 0: GO TO 170
230 IF ba = 1 THEN PRINT AT by, bx; INK 7; CHR$ 148
240 GO TO 170
500 DATA 0
How It Works
Lines 100-140 form the main loop. INKEY$ reads the keyboard without pausing. If no key is pressed, the program continues immediately — no waiting, no INPUT prompt. The game runs as fast as BASIC can manage.
Lines 110-120 handle movement. When the player presses O, the ship moves left: print a space at the current position (erase), decrease the column variable, print the ship at the new position (redraw). P does the same in the opposite direction. Boundary checks prevent the ship from leaving the screen.
Line 130 handles firing. When SPACE is pressed, a bullet appears at the row above the ship. Variables track the bullet position and whether it is active.
Lines 150-170 move the bullet upward. Each pass through the loop, the bullet erases its current position, decreases its row by one, and draws at the new position. When it reaches the top of the screen, it disappears and the active flag resets.
The Erase-Redraw Pattern
Moving a character on screen requires two steps:
- Erase: Print a space at the old position.
- Redraw: Print the character at the new position.
Skip the erase step and you get a trail of characters. Skip the redraw step and the character vanishes. Both steps, every frame, for every moving object. This pattern is the foundation of all movement in BASIC games.
INKEY$ vs INPUT
INPUT pauses the program and waits for the player to type something and press ENTER. That works for turn-based games. For a real-time shooter, you need INKEY$ — it reads the keyboard instantly and returns whatever key is currently held down, or an empty string if nothing is pressed. The game loop never stops.
Try This
Adjust the speed. The bullet moves one row per loop iteration. What happens if you move it every other iteration instead? Add a counter variable and only move the bullet when the counter is even. Does it feel better or worse?
Fire downward. Change the bullet to move down instead of up. Now you have the basic mechanic for enemy bombs — a projectile that falls toward the player.