Skip to content
Game 2

Make contact matter

Calculate the next position, resolve contact and turn a moving display into a rally game.

At present the ball turns even if the paddle is nowhere near it. We need one clear rule: arriving beside an occupied paddle row is a return; arriving outside those rows is a miss.

Continue from Move the paddle, with the program stopped. This change reorganises movement, so enter the full set of edits before running it.

Replace lines 200, 210, 220, 230, 240, 250. Add lines 26, 245, 600, 610, 620, 630, 700.

26 LET missed=0
200 LET nx=x+dx: LET ny=y+dy
210 IF ny=2 THEN LET dy=1: LET ny=4
220 IF ny=20 THEN LET dy=-1: LET ny=18
230 IF nx=30 THEN LET dx=-1: LET nx=28
240 IF nx=2 THEN GO SUB 600
245 IF missed=1 THEN GO TO 700
250 LET x=nx: LET y=ny
600 IF ny<p THEN LET missed=1: RETURN
610 IF ny>p+2 THEN LET missed=1: RETURN
620 LET dx=1: LET nx=4
630 RETURN
700 PRINT AT 21,1;"Miss. RUN to try again.": STOP

Decide before drawing

Previously we changed x and y, then changed a direction at an inner limit. Now we calculate a candidate position, nx and ny, meaning “where this step would take the ball”. We can inspect and adjust it before it becomes the position we draw.

LET nx=x+dx does not change x. That separation gives us somewhere to resolve contact. Once the checks are finished, line 250 copies the candidate into x and y for the next drawing.

At the top, a candidate row of 2 would be inside the wall. Set dy to 1 and the candidate row to 4 instead: the ball leaves row 3 and takes its next step inward. The bottom rule changes a candidate 20 to 18. At the right wall, candidate column 30 becomes 28 and dx becomes −1. These rules preserve the one-cell path beside the walls while putting the decision before drawing.

Which row reaches the paddle?

A candidate column of 2 means the ball is arriving at the paddle column. Given our limits and one-cell steps, it can reach that column only from column 3 while travelling left. That is when line 240 calls the contact routine.

The routine tests the candidate row after vertical contact has been resolved:

  • If ny is less than p, it is above the paddle.
  • If ny is greater than p+2, it is below the paddle.
  • Otherwise it is in one of the paddle’s three rows, including either endpoint.

On a hit, set dx to 1 and nx to 4. The ball moves back into the court without printing over the paddle. On a miss, set missed to 1 and return. We initialise that flag to 0 at the start: zero means no miss; one means the rally has ended.

Both outcomes return to the main loop. Line 245 then sends a miss to the result at 700, which prints a message and stops. We do not jump out of the subroutine straight into another game: returning first completes the call properly.

Trace the edge cases

With p=9, the paddle covers rows 9–11. A candidate row of 9 or 11 is a hit; 8 or 12 is a miss. The strict < and > tests deliberately leave the endpoints inside the accepted interval.

The ball is at row 3, column 3, moving up and left. The paddle starts at row 3. What happens next?

Show the explanation

The first candidate is row 2, column 2. The top-wall rule changes its row to 4 and its vertical direction to down. Row 4 is inside the paddle’s rows 3–5, so the paddle returns it to column 4. The next drawing is at row 4, column 4, travelling down and right. This follows our stated order of contact checks.

Play the first rally

Run the program. Use A and Z to meet the returning ball. It can now escape on the left, producing Miss. RUN to try again. and the intentional STOP report. RUN starts another attempt. Q still stops during play.

The paddle will not rescue a ball merely by being close. Compare its occupied rows with the row where the ball arrives. If every approach returns regardless of paddle position, check that the old unconditional left-boundary rule has been replaced. If a new run immediately reports a miss, check line 26 resets missed to zero.

This is a small, discrete collision model. We are not calculating curved surfaces, spin or the point where two continuous paths intersect. Its virtue here is that we can trace every decision and compare it with the display.

Complete rally program
10 BORDER 0: PAPER 0: INK 7: CLS
20 LET x=15: LET y=10: LET dx=1: LET dy=1
25 LET p=9
26 LET missed=0
30 PRINT AT 0,1;"VOLLEY"
40 FOR c=2 TO 30: PRINT AT 2,c;"-";AT 20,c;"-": NEXT c
50 FOR r=3 TO 19: PRINT AT r,30;"I": NEXT r
90 GO SUB 500
100 PRINT AT y,x;"o"
105 LET k$=INKEY$
106 IF k$="q" THEN STOP
110 PAUSE 2
120 PRINT AT y,x;" "
125 IF k$="a" THEN IF p>3 THEN PRINT AT p+2,2;" ": LET p=p-1
126 IF k$="z" THEN IF p<17 THEN PRINT AT p,2;" ": LET p=p+1
130 GO SUB 500
200 LET nx=x+dx: LET ny=y+dy
210 IF ny=2 THEN LET dy=1: LET ny=4
220 IF ny=20 THEN LET dy=-1: LET ny=18
230 IF nx=30 THEN LET dx=-1: LET nx=28
240 IF nx=2 THEN GO SUB 600
245 IF missed=1 THEN GO TO 700
250 LET x=nx: LET y=ny
300 GO TO 100
500 FOR r=p TO p+2: PRINT AT r,2;"I": NEXT r
510 RETURN
600 IF ny<p THEN LET missed=1: RETURN
610 IF ny>p+2 THEN LET missed=1: RETURN
620 LET dx=1: LET nx=4
630 RETURN
700 PRINT AT 21,1;"Miss. RUN to try again.": STOP

Sources

Steven Vickers, edited by Robin Bradbeer, ZX Spectrum BASIC Programming, second edition (Sinclair Research, 1983), chapters 3, 5 and 7 (conditions, subroutines and expressions). The contact rules are the model implemented in this game.