This program implements a simple asteroid-dodging game for the ZX81/TS1000. Asteroids fall down the screen using SCROLL to advance them, while the player moves a small ship (represented by block graphics) left and right with keys 5 and 8. The score increments each loop by a speed variable T, which doubles to 2 at score 104; the asteroid graphic also changes at score 100 from a simple two-character block to a wider four-character boulder shape. Collision detection checks whether the ship’s X position falls within a range of the oldest asteroid’s column (E), using a tolerance window adjusted by T.
Program Analysis
Program Structure
The program is organized into two sections: an initialization block (lines 10–135) that sets up variables and the ship’s starting position, and a main game loop (lines 160–300) that generates, displays, and scrolls asteroids while handling player input and collision detection. A short crash/end sequence lives at lines 500–520, and lines 530–540 are utility lines for saving and restarting.
Variable Roles
| Variable | Purpose |
|---|---|
A$ | Asteroid graphic string (changes at N=100) |
N | Score counter (increments by T each loop) |
T | Speed/step factor (starts 1, doubles to 2 at N=104) |
X | Ship horizontal position (starts at column 12) |
R | Current asteroid column (random 0–26) |
A,B,C,D,E | Shift register of last five asteroid columns |
Asteroid Movement and SCROLL
Each loop iteration calls SCROLL twice (lines 180–190), advancing the screen upward by two rows per cycle. The asteroid is printed at row 21 (the bottom), so after two scrolls it will appear to move up the screen. The ship is fixed at row 11, roughly in the middle of the display. This approach is elegant but means the frame rate is entirely tied to the BASIC interpreter’s speed.
Shift-Register Collision Detection
Lines 215–250 implement a five-stage shift register: each loop, the previous values of R are shifted through A→B→C→D→E. E therefore holds the column of the asteroid printed five loops ago. Because two scrolls advance content by two rows per loop, after five loops an asteroid originally at row 21 will have moved to approximately row 11 — the ship’s row. The collision check at line 270 then tests whether X is within the window [E-2, E+T], catching the ship overlapping the asteroid at the correct time.
The window is intentionally asymmetric: left margin is always 2, while the right margin uses T (1 or 2). This is a minor balance quirk — at speed 2, the right-side hit zone becomes slightly wider than the left.
Difficulty Progression
Two milestone checks trigger as the score N increases:
- At
N=100: the asteroid graphicA$changes from\##(a 2-char block) to\.'\.(a 4-char wider boulder using ZX81 block graphics), making it harder to dodge. - At
N=104: speed variableTdoubles from 1 to 2, causing the ship to move and the score to increment faster, and also widening the right collision margin slightly.
Ship and Erase Graphics
The ship is drawn at row 11 using the block-graphic string \'.\'.' at line 260, which produces a small chevron/arrow shape. Line 255 erases the ship’s previous position by printing six spaces at AT 9,X-2 — note this erases two rows above the ship’s actual row 11, which may be a minor off-by-one: the erase row (9) does not match the draw row (11). In practice, since the ship graphic does not change row between frames (X is the only variable), this discrepancy means the old ship image at row 11 is never explicitly erased — it is instead overwritten naturally by SCROLL advancing the screen contents upward.
Input Handling
Movement keys are polled with bare INKEY$ at lines 280–290 with no debounce or wait. Key “5” moves left (decrements X by T), key “8” moves right (increments X by T). There is no boundary clamping, so X can be driven off the left or right edge of the screen, causing the ship and erase prints to wrap or error.
Notable Techniques
- Double
SCROLLper frame gives a faster apparent asteroid speed without requiring complex position tracking. - The shift register pattern (lines 215–250) is a clean BASIC idiom for delayed collision detection, avoiding any need to track individual asteroid objects.
- Score is accumulated by adding
Teach loop rather than 1, so it naturally reflects speed — both as a reward for surviving longer and as a trigger for the difficulty events at 100 and 104.
Bugs and Anomalies
- The ship erase at
AT 9,X-2targets row 9, not row 11 where the ship is drawn. The ship silhouette at row 11 is never explicitly cleared; it disappears only when scrolled off naturally. - No boundary check on
Xmeans the player can steer the ship off-screen entirely. - At speed
T=2,INKEY$is read twice per loop (lines 280 and 290) but with no loop delay, so both checks may see the same key simultaneously, causing a net move of+2Tor no move rather than the intended exclusive left/right step.
Content
Source Code
10 REM "ASTEROIDS"
100 LET A$="\##"
105 LET N=0
110 LET A=0
115 LET B=0
120 LET C=0
125 LET D=0
130 LET T=1
135 LET X=12
160 LET R=INT (RND*27)
170 PRINT AT 21,R;A$
180 SCROLL
190 SCROLL
200 LET N=N+T
205 IF N=100 THEN LET A$="\.'\. "
210 IF N=104 THEN LET T=2
215 LET E=D
220 LET D=C
230 LET C=B
240 LET B=A
250 LET A=R
255 PRINT AT 9,X-2;" "
260 PRINT AT 11,X;"\'.\.'"
270 IF X>=E-2 AND X<=E+T THEN GOTO 500
280 IF INKEY$="5" THEN LET X=X-T
290 IF INKEY$="8" THEN LET X=X+T
300 GOTO 160
500 PRINT AT 11,X-1;"CRASH"
510 PRINT AT 0,0;"SCORE= ";N
520 STOP
530 SAVE "1017%9"
540 RUN
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
