Keep the ball visible
Compare drawing orders and update only the cells that change.
The blue court looks stronger, but the ball still spends too long missing from it. In the current loop, we erase the ball before handling the paddle and calculating contact. The player sees an empty cell while BASIC does that work.
Keep a saved copy of Colour the court for comparison. Then stop the game and make these edits:
Replace lines 125, 126, 300. Add line 248. Delete lines 120, 130.
125 IF k$="a" THEN IF p>3 THEN PRINT AT p+2,2;" ": LET p=p-1: PRINT PAPER 6;AT p,2;" "
126 IF k$="z" THEN IF p<17 THEN PRINT AT p,2;" ": LET p=p+1: PRINT PAPER 6;AT p+2,2;" "
248 PRINT AT y,x;" ";AT ny,nx;"o"
300 GO TO 105
Calculate while the current ball is visible
The current image does not prevent us calculating nx and ny. Leave it alone
while reading input, updating the paddle and resolving contact. Once the next
position is known, line 248 prints a blue space at the old position and the ball
at the new position, consecutively in the same PRINT statement.
Only then do we store nx and ny in x and y. We still need the old values
when clearing the old cell. Assigning the new values first would make us erase
the destination and leave the previous ball behind.
Line 100 draws the initial ball once. Line 300 now returns to 105, the input reading, because line 248 has already drawn each later position. We remove the early erase at 120 rather than adding a second erase somewhere else.
| Part of an update | Earlier version | Revised version |
|---|---|---|
| Read input and pause | Ball visible | Ball visible |
| Handle paddle and contact | Ball already erased | Current ball stays visible |
| Display the next position | On the next trip to line 100 | Immediately after clearing the old cell |
Does keeping the ball visible mean we are calculating from an old position by mistake?
Show the explanation
No. x and y are the current position; nx and ny are the candidate next
position. Those are different jobs. We calculate the candidate from the current
position, resolve contact, then update the picture and stored position together.
Draw only the paddle cells that change
The old loop redrew all three paddle cells every time, even with no key pressed.
Remove that unconditional call at 130. On upward movement, clear the old bottom
cell, decrease p, then draw the new top cell in yellow. Downward movement clears
the old top, increases p and draws the new bottom.
The two overlapping cells stay yellow throughout. The routine at 500 is still useful for the initial drawing at line 90; it is not needed for every update. This is a small example of selective redrawing: spend work on the cells whose contents actually change.

Compare what changes—and what doesn’t
Run the two saved versions in turn. Follow the ball between contacts rather than judging a still picture. It should spend much less time invisible in the revised version. Check that the same contacts still count as returns and misses, and that old paddle cells return to blue.
In the checked 48K emulator run, the colour-only version had no decoded ball in 206 of 328 sampled screen-memory frames. The revised loop had none of those gaps across 204 sampled frames, and followed the same sequence of positions. Those measurements describe screen memory in that run, not a guarantee that no display artefact is possible on every system.
The shorter run also tells us something: doing less work changes the pace.
Both versions request PAUSE 2, but the other instructions take time too, and
keys can shorten PAUSE. Compare responsiveness as well as visibility. We have
not created a fixed-frame scheduler or smooth pixel movement; the ball still
moves one character cell per update.
Would a screenshot be enough to decide whether the flashing improved?
Show the explanation
No. Either version can produce a frame with the ball present. We need to watch movement, or measure visibility over time with the method and its limits stated. A still image is useful for checking colour and layout instead.
Complete Volley program to keep
10 BORDER 0: PAPER 0: INK 7: BRIGHT 1: CLS
15 PRINT AT 3,3;"VOLLEY";AT 5,3;"A up Z down";AT 7,3;"Q quits. Keep the rally going.";AT 9,3;"S to serve": GO SUB 800: CLS
20 LET x=15: LET y=10: LET dx=1: LET dy=1
25 LET p=9: LET score=0
26 LET missed=0
30 PRINT AT 0,1;"VOLLEY Returns: ";score
35 PAPER 1: FOR r=3 TO 19: PRINT AT r,2;" ": NEXT r
40 FOR c=2 TO 30: PRINT PAPER 5;AT 2,c;" ";AT 20,c;" ": NEXT c
50 FOR r=3 TO 19: PRINT PAPER 5;AT r,30;" ": NEXT r
90 GO SUB 500
100 PRINT AT y,x;"o"
105 LET k$=INKEY$
106 IF k$="q" THEN GO TO 900
110 PAUSE 2
125 IF k$="a" THEN IF p>3 THEN PRINT AT p+2,2;" ": LET p=p-1: PRINT PAPER 6;AT p,2;" "
126 IF k$="z" THEN IF p<17 THEN PRINT AT p,2;" ": LET p=p+1: PRINT PAPER 6;AT p+2,2;" "
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
248 PRINT AT y,x;" ";AT ny,nx;"o"
250 LET x=nx: LET y=ny
300 GO TO 105
500 FOR r=p TO p+2: PRINT PAPER 6;AT r,2;" ": 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: LET score=score+1: PRINT PAPER 0;AT 0,19;score
630 RETURN
700 PRINT PAPER 0;AT 21,1;"Miss. R retry, Q quit."
710 IF INKEY$<>"" THEN GO TO 710
720 LET k$=INKEY$: IF k$="q" THEN GO TO 900
730 IF k$<>"r" THEN GO TO 720
740 IF INKEY$<>"" THEN GO TO 740
750 GO TO 10
800 IF INKEY$<>"" THEN GO TO 800
810 LET k$=INKEY$: IF k$="q" THEN GO TO 900
820 IF k$<>"s" THEN GO TO 810
830 IF INKEY$<>"" THEN GO TO 830
840 RETURN
900 PRINT PAPER 0;AT 21,1;"Finished. ": STOP
Keep a playable copy
Save the final program as volley, keeping the earlier comparison version under
a different name. The Meet BASIC saving guide
explains recording and exporting a tape. Use SAVE "volley"; an exported tape
file and the name stored inside it are separate things.
Load the saved tape in a fresh session with LOAD "volley", then RUN. Check
serve, a rally, a miss, retry and quit. A source listing is valuable, but a saved
game is only ready to share once it can be reopened and played.
We now have movement, contact and a complete play cycle, with a deliberate approach to drawing. Touchdown reuses these ideas while changing the speed of the craft itself through gravity and thrust.
Sources
Steven Vickers, edited by Robin Bradbeer, ZX Spectrum BASIC Programming, second edition (Sinclair Research, 1983), chapters 15–16 (printing and colour), chapter 18 (motion and PAUSE), and chapter 20 (tape storage). The visibility figures come from the maintained Volley drawing comparison on Emu198x Spectrum 0.22.1 in 48K PAL configuration.