Skip to content
Game 2

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.

A white ball on a blue court with cyan walls, a solid yellow paddle on the left and a black score strip.
The final court held still for colour and layout inspection. A still frame cannot establish how the movement looks.

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.