Skip to content
Game 14 Unit 7 of 32 1 hr learning time

The HUD

Score, high score, lives and wave number — a status bar that stays visible during play.

22% of Blockstorm

The player needs information: how many points, how many lives, which wave. This unit adds a heads-up display across the top row of the screen. The HUD updates every frame to show the current score, high score, lives remaining and wave number. BRIGHT 1 makes the text stand out from the dark play area below.

The Program

5 REM === THE HUD ===
10 BORDER 0: PAPER 0: INK 7: CLS
15 GO SUB 800
20 LET sc = 0: LET hi = 0: LET li = 3
22 LET wv = 1
30 LET px = 15: LET py = 20
40 GO SUB 600
50 PRINT AT py, px; INK 7; CHR$ 152
60 REM === game loop ===
70 LET k$ = INKEY$
80 IF k$ = "o" OR k$ = "O" THEN IF px > 1 THEN PRINT AT py, px; " ": LET px = px - 1: PRINT AT py, px; INK 7; CHR$ 152
90 IF k$ = "p" OR k$ = "P" THEN IF px < 30 THEN PRINT AT py, px; " ": LET px = px + 1: PRINT AT py, px; INK 7; CHR$ 152
100 IF k$ = " " THEN IF ba = 0 THEN LET bx = px: LET by = py - 1: LET ba = 1: PRINT AT by, bx; INK 7; CHR$ 148
110 IF ba = 0 THEN GO TO 60
120 PRINT AT by, bx; " "
130 LET by = by - 1
140 IF by < 1 THEN LET ba = 0: GO TO 60
150 PRINT AT by, bx; INK 7; CHR$ 148
160 GO TO 60
600 REM === draw HUD ===
605 PRINT AT 0, 0; INK 7; BRIGHT 1; "SC:"; sc; "  HI:"; hi; "  LV:"; li; " W"; wv; "  "
610 RETURN
800 REM === define UDGs ===
805 FOR i = 0 TO 13
810 FOR j = 0 TO 7
815 READ a
820 POKE USR CHR$ (65 + i) + j, a
825 NEXT j
830 NEXT i
835 RETURN
840 REM UDG A: drone
842 DATA 36, 126, 219, 255, 255, 102, 66, 0
844 REM UDG B: scout
846 DATA 24, 60, 126, 255, 219, 24, 36, 0
848 REM UDG C: tank
850 DATA 126, 255, 255, 255, 255, 255, 126, 0
852 REM UDG D: bomber
854 DATA 66, 231, 255, 126, 60, 90, 36, 0
856 REM UDG E: bullet
858 DATA 16, 56, 16, 16, 0, 0, 0, 0
860 REM UDG F: explosion
862 DATA 36, 153, 66, 129, 66, 153, 36, 0
864 REM UDG G: double shot
866 DATA 84, 170, 84, 170, 84, 170, 84, 0
868 REM UDG H: shield
870 DATA 60, 126, 255, 255, 255, 126, 60, 0
872 REM UDG I: player ship
874 DATA 16, 56, 56, 124, 254, 254, 130, 0
876 REM UDG J: enemy bomb
878 DATA 16, 16, 56, 16, 0, 0, 0, 0
880 REM UDG K: explosion 2
882 DATA 129, 66, 36, 0, 36, 66, 129, 0
884 REM UDG L: shield icon
886 DATA 60, 126, 126, 126, 60, 24, 0, 0
888 REM UDG M: drone frame 2
890 DATA 66, 102, 255, 255, 219, 126, 36, 0
892 REM UDG N: scout frame 2
894 DATA 36, 24, 219, 255, 126, 60, 24, 0

How It Works

Lines 600-610 are the HUD drawing routine. A single PRINT AT statement at row 0, column 0 writes all the status information in one go. INK 7 makes the text white. BRIGHT 1 makes it brighter than the game graphics below — a visual distinction between information and action.

The semicolons chain multiple values together in one PRINT statement. "SC:"; sc prints the label followed by the current value of the score variable. The trailing spaces at the end clear any leftover characters from previous values (important when a number shrinks in digit count, which does not happen with scores that only go up, but matters for other values).

Line 130 calls GO SUB 600 inside the main game loop. The HUD redraws every frame. This is simple but effective — the score is always current, the lives count always accurate.

Row 0 is Reserved

The play area runs from row 1 to row 21. Row 0 belongs to the HUD. The ship sits at row 20. Enemies descend from row 2 downward. Nothing in the game should overwrite row 0 — it is status territory.

BRIGHT 1

BRIGHT 1 makes characters appear at double intensity. On a real Spectrum, this is a noticeable difference — bright white is noticeably whiter than normal white. Using BRIGHT 1 for the HUD and normal brightness for the game creates a visual layer: the status bar feels separate from the action, even though it is on the same screen.

Formatting Numbers

Sinclair BASIC prints numbers with a leading space for positive values (where a minus sign would go for negatives). This means PRINT 42 actually prints 42 with a space before it. For the HUD, this is fine — the spacing looks reasonable. For precise alignment, you would need to convert numbers to strings and trim spaces, but in a fast-moving shooter, nobody notices.

Try This

Add a lives display using UDGs. Instead of printing the number of lives, print that many ship UDGs (CHR$ 152) in a row. Three lives = three tiny ships. It looks better and uses the custom characters you have already defined.

Test with large scores. Set sc to 99999 at the start. Does the HUD still fit on one row? What is the maximum score that fits without overflowing? Plan for this now to avoid display bugs later.