The ball now has a position and a way to erase itself. Give it a direction, then repeat a small sequence: read a key, propose a move, check it, erase the old ball and draw the new one.
The first moving version bounces off the sides and top. It stops when it reaches the space where our paddle will go.
Delete lines 20, 30, 1040.
Replace lines 10, 1000.
Add lines 100, 110, 130, 200, 210, 220, 350, 360, 370, 380, 390, 490, 500, 510, 1010, 1020, 1090, 1100, 4000, 4010, 4020, 4030, 4040, 4050, 4060, 9000.
Delete a BASIC line by entering its number on its own. The listing below contains only the lines to enter or replace.
10 GO TO 100
100 LET x=127: LET y=40
110 LET dx=4: LET dy=4: LET steps=0
130 GO SUB 1000: GO SUB 3000
200 LET k$=INKEY$
210 IF k$="q" OR k$="Q" THEN GO TO 9000
220 IF k$="r" OR k$="R" THEN GO TO 100
350 LET nx=x+dx: LET ny=y+dy
360 IF nx<16 THEN LET nx=32 -nx: LET dx=ABS dx
370 IF nx>238 THEN LET nx=476 -nx: LET dx=-ABS dx
380 IF ny>149 THEN LET ny=298 -ny: LET dy=-ABS dy
390 IF ny<32 THEN LET e$="Ball reached the bottom.": GO TO 4000
490 GO SUB 3000
500 LET x=nx: LET y=ny: LET steps=steps+1
510 GO SUB 3000: GO TO 200
1000 BORDER 0: PAPER 0: INK 7: CLS
1010 PRINT AT 0,2; INK 5;"BRICK BASH"
1020 PRINT AT 1,2;"Watch the ball bounce."
1090 PRINT AT 21,2; INK 5;"R retry Q quit";
1100 RETURN
4000 PRINT AT 1,0;" ";AT 1,2; INK 6;e$
4010 PRINT AT 21,2; INK 7;"R plays again Q quits ";
4020 IF INKEY$<>"" THEN GO TO 4020
4030 LET k$=INKEY$
4040 IF k$="q" OR k$="Q" THEN GO TO 9000
4050 IF k$="r" OR k$="R" THEN GO TO 100
4060 GO TO 4030
9000 PAPER 0: INK 7: PRINT AT 21,0;"Finished. RUN to try again. ";: STOPRUN the changed program.
Complete source at this checkpoint
10 GO TO 100
100 LET x=127: LET y=40
110 LET dx=4: LET dy=4: LET steps=0
130 GO SUB 1000: GO SUB 3000
200 LET k$=INKEY$
210 IF k$="q" OR k$="Q" THEN GO TO 9000
220 IF k$="r" OR k$="R" THEN GO TO 100
350 LET nx=x+dx: LET ny=y+dy
360 IF nx<16 THEN LET nx=32 -nx: LET dx=ABS dx
370 IF nx>238 THEN LET nx=476 -nx: LET dx=-ABS dx
380 IF ny>149 THEN LET ny=298 -ny: LET dy=-ABS dy
390 IF ny<32 THEN LET e$="Ball reached the bottom.": GO TO 4000
490 GO SUB 3000
500 LET x=nx: LET y=ny: LET steps=steps+1
510 GO SUB 3000: GO TO 200
1000 BORDER 0: PAPER 0: INK 7: CLS
1010 PRINT AT 0,2; INK 5;"BRICK BASH"
1020 PRINT AT 1,2;"Watch the ball bounce."
1030 PLOT INK 1;15,16: DRAW INK 1;0,136: DRAW INK 1;225,0: DRAW INK 1;0,-136
1090 PRINT AT 21,2; INK 5;"R retry Q quit";
1100 RETURN
3000 PLOT INK 7; OVER 1;x,y: DRAW INK 7; OVER 1;1,0: DRAW INK 7; OVER 1;0,1: DRAW INK 7; OVER 1;-1,0: RETURN
4000 PRINT AT 1,0;" ";AT 1,2; INK 6;e$
4010 PRINT AT 21,2; INK 7;"R plays again Q quits ";
4020 IF INKEY$<>"" THEN GO TO 4020
4030 LET k$=INKEY$
4040 IF k$="q" OR k$="Q" THEN GO TO 9000
4050 IF k$="r" OR k$="R" THEN GO TO 100
4060 GO TO 4030
9000 PAPER 0: INK 7: PRINT AT 21,0;"Finished. RUN to try again. ";: STOPA direction is two changes
Line 110 starts dx and dy at 4. Adding dx moves right; adding dy moves up. A negative value reverses that axis. Line 350 puts the proposed coordinates in nx and ny while x and y still describe the visible ball.
Keep those pairs separate. We may alter a proposed move or reject it entirely before touching the old picture. steps counts committed moves; it is a useful trace counter, not a clock or score.
Bounce the overshoot back
The ball occupies x through x+1. With walls at 15 and 240, its lower-left x must stay between 16 and 238. Its top pixel is y+1, so y must stay at or below 149, leaving a clear pixel below the court’s top line at 152.
Suppose a move proposes nx=239. It is one pixel beyond the right limit 238. Reflecting it gives 238−1=237. Line 370 writes that as 476-nx: twice the boundary minus the proposed position.
The other reflection formulas follow the same idea. 32-nx reflects around x=16, and 298-ny reflects around y=149. ABS dx removes the sign; assigning a negative absolute value guarantees leftward movement, while a positive one guarantees rightward movement.
A candidate x of 242 is four pixels beyond 238. Where does the reflection put it?
Show the explanation
At 234: 476−242. We bring the overshoot back inside, rather than placing the ball on the wall and forgetting how far it travelled.
Commit one move
Line 490 toggles the old ball off. Line 500 copies nx/ny into x/y and increments steps. Line 510 draws at the new position and returns to keyboard polling. A subroutine call returns; GO TO changes where execution continues without keeping a return address.
INKEY$ reads a key without waiting for one. With no key, k$ is an empty string and the ball still moves. Q branches to the exit routine; R returns to line 100 to rebuild the initial state. The comparisons accept both lower- and upper-case letters.
An IF condition controls the rest of its BASIC line. In line 390, both assigning e$ and jumping to 4000 happen only when ny is below 32. That candidate is rejected: the last valid ball remains visible.
Stop, retry, leave
The result routine clears the old message, prints e$ and offers R/Q. Line 4020 waits until the previous key is released. Otherwise a held key could immediately carry us into another attempt. The later polling loop waits for the next choice.
RUN it without touching a key. Watch the right wall and top reflection, then the bottom stop. Retry with R and leave with Q. To investigate the left wall, temporarily give dx the value -4 in line 110, predict the first bounce and run again. Restore dx=4 afterwards.
If a trail remains, check the order of lines 490–510. If the ball never moves, check GO TO 200 at the end of line 510. This loop has no deliberate delay. Its pace comes from the work BASIC performs, so later stages can move more slowly.
Sources
Steven Vickers, edited by Robin Bradbeer, ZX Spectrum BASIC Programming, second edition (Sinclair Research, 1983), chapters 3–6 and 17–18.
Run it here
This unit's program, built for you.
- Program
- brick-bash.tap
- Machine
- ZX Spectrum 48K (PAL)