This program is a single-player driving game in which the player steers a car (rendered using four custom UDG characters) along a road that converges toward a vanishing point, simulating a 3D perspective view. The car’s horizontal position is tracked by variable `p`, and the road edges are drawn each frame using PLOT/DRAW commands that project lines from the bottom of the screen to a horizon point. Random lateral drift is added each tick via `INT (RND*20)-10`, making steering progressively challenging. A score counter increments each frame the player stays on the road, and a crash triggers a descending BEEP tone sequence before prompting for replay. The UDGs (chars `\a` through `\d`) are defined by POKEing 32 bytes of bitmap data read from DATA statements at lines 9030–9060, forming the front view of a vehicle sprite.
Program Analysis
Program Structure
The program is organized into several distinct sections:
- Initialization (lines 20–30): Two subroutines set up UDG data and the screen, then the main loop begins.
- Main game loop (lines 40–120): Draws the car sprite, checks boundary conditions, renders road perspective lines with XOR overdraw for erasure, reads player input, applies random drift, and increments the score.
- Crash handler (lines 1000–1050): Redraws the car in FLASH/INK 2, plays a sound effect, displays the score, and prompts for replay.
- Screen setup subroutine (lines 8000–8990): Sets colors, clears the screen, resets
pandsc, and draws a top status bar. - UDG loader subroutine (lines 9000–9060): Reads 32 bytes from DATA and POKEs them into UDG addresses
USR "a"throughUSR "d"+7. - Remarks and save (lines 9500–9999): Visual reference comments showing the UDG layout, followed by SAVE/VERIFY.
Road Perspective Drawing
The 3D road illusion is achieved with two PLOT/DRAW pairs. The left road edge is drawn from (p-10, 159) — the bottom of the screen near the car — to a vanishing point, using DRAW -170+(p-10), -159. The right edge similarly uses DRAW -70+(p-10), -159. These expressions mean the horizontal endpoint of each line shifts with the car’s position p, so the road always appears to lead toward where the car is heading, reinforcing the perspective effect.
Lines 80–90 repeat the same PLOT/DRAW calls with OVER 1, which XOR-erases the previously drawn road lines before the next frame is rendered. This is a standard flicker-free animation technique on this platform, avoiding a full CLS each frame.
Car Sprite via UDGs
The car is a 2×2 grid of UDG characters (\a\b on the top row, \c\d on the bottom), displayed with PRINT AT 15,15. The 32 bytes of bitmap data across DATA lines 9030–9060 define the pixel patterns. Line 9500–9510 serve as a developer reference comment showing the intended layout of the four UDG characters.
Input and Drift Mechanics
Player steering is handled at line 100 using a compact Boolean arithmetic idiom:
p = p + 4*(INKEY$="5") - 4*(INKEY$="8")— pressing “5” moves left, “8” moves right, each by 4 pixel units per frame.
Line 110 immediately applies random drift: INT (RND*20)-10 produces a value in the range −10 to +9 each tick, making the car wander and increasing difficulty over time regardless of player input.
Boundary Detection and Crash
Line 50 tests whether p has gone out of the safe range 108–150. If so, control jumps to line 1000 (crash handler) rather than looping back. On a crash, lines 1000–1010 draw the final road position (without erasing), and line 1020 redraws the car sprite with FLASH 1; INK 2 to signal a collision.
Sound Effect
The crash sound at line 1030 uses a FOR loop from 0 to 50, playing two BEEP calls per iteration (BEEP .05,a and BEEP .0008,a), producing a rising two-tone sweep that mimics a crash/alarm effect.
Notable Techniques and Idioms
- Boolean arithmetic for input:
4*(INKEY$="5")evaluates the comparison as 1 (true) or 0 (false) and scales it, avoiding an IF/THEN branch. - OVER 1 for erasure: XOR plotting the same lines removes them without clearing the whole screen, preserving the status bar and sprite.
- LINE input for replay prompt:
INPUT ... LINE a$captures any ENTER keypress without requiring the user to type a specific value. - Delay loop:
FOR z=1 TO 120: NEXT zon line 1050 introduces a brief pause after the score display before restarting. - Unused line 1320:
GO TO 50at line 1320 is never reached by normal program flow and appears to be a dead code remnant.
Potential Bugs and Anomalies
| Line | Issue |
|---|---|
50 | Boundary check uses p<108 OR p>150 but no road erase occurs before the crash jump, so the last road frame stays on screen — this is by design (lines 1000–1010 redraw it). |
100 | Both INKEY$ calls are evaluated independently in the same statement; if both “5” and “8” are somehow pressed simultaneously (not possible on a real keyboard), the movements cancel. Not a real-world bug. |
1320 | Unreachable dead code — GO TO 50 with no path leading to line 1320. |
8040 | The status bar uses 32 underscores printed at AT 0,0 but the screen is 32 columns wide, which is correct; however, PAPER 1 is only set for this PRINT, so the bar background relies on the INK/PAPER state rather than a persistent attribute — consistent with the PAPER 0 set at line 8000. |
Content
Source Code
10 REM 3D DRIVER from Games for Your Timex-Sinclair 2000, p.74
20 GO SUB 9000
30 GO SUB 8000
40 PRINT AT 15,15; INK 4;"\a\b";AT 16,15;"\c\d"
50 IF p<108 OR p>150 THEN GO TO 1000
60 PLOT p-10,159: DRAW -170+(p-10),-159
70 PLOT p+10,159: DRAW -70+(p-10),-159
80 PLOT OVER 1;p-10,159: DRAW OVER 1;-170+(p-10),-159
90 PLOT OVER 1;p+10,159: DRAW OVER 1;-70+(p-10),-159
100 LET p=p+4*(INKEY$="5")-4*(INKEY$="8")
110 LET p=p+(INT (RND*20)-10)
115 LET sc=sc+1
120 GO TO 50
990 STOP
1000 PLOT p-10,159: DRAW -170+(p-10),-159
1010 PLOT p+10,159: DRAW -70+(p-10),-159
1020 PRINT AT 15,15; FLASH 1; INK 2;"\a\b";AT 16,15;"\c\d"
1030 FOR a=0 TO 50: BEEP .05,a: BEEP .0008,a: NEXT a
1040 PRINT AT 1,10; PAPER 1;"You scored ";sc
1050 INPUT "Press "; INK 6;"ENTER"; INK 7;" to play again "; LINE a$: FOR z=1 TO 120: NEXT z: GO TO 30
1320 GO TO 50
7000 REM
8000 BORDER 0: PAPER 0: INK 7: CLS
8010 LET p=127
8020 LET sc=0
8040 PRINT AT 0,0; PAPER 1;"________________________________"
8990 RETURN
9000 FOR a=USR "a" TO USR "d"+7
9010 READ user: POKE a,user
9020 NEXT a: RETURN
9030 DATA 0,0,0,0,13,11,13,3
9040 DATA 0,0,0,0,176,208,175,192
9050 DATA 6,117,207,223,208,240,12,3
9060 DATA 102,174,243,251,19,15,48,192
9500 REM ab cd
9510 REM \a\b \c\d
9998 SAVE "Driver" LINE 0
9999 VERIFY ""
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
