Overview
A 28-cell horizontal bar that fills proportionally to a value, changing colour at thresholds: blue (cold/low) → yellow (warm/medium) → red (hot/high) → white (maximum). Uses PRINT AT with PAPER colours. Ideal for temperature bars, health bars, timer displays, or any value shown spatially rather than numerically.
True-zero behaviour
The cell count is INT(v*28/vm) clamped to 0-28. When v = 0 the bar is entirely empty — no cells lit. When v = vm (maximum), all 28 cells are lit. When v > vm, the bar saturates at 28. Negative values clamp to 0.
Earlier versions of this pattern used h = INT(v*28/vm) + 1 which always lit at least one cell even at zero. That hid the difference between "empty" and "barely above empty" — fixed in the current version so v=0 visibly means empty.
Underlying mechanism
PRINT AT with PAPER writes a space character (which is "blank" in display memory) plus an attribute byte (which sets the cell's PAPER colour). Because each character cell is 8×8 pixels, the bar is 28 cells × 8 = 224 pixels wide, a whole pixel band tall. The block of solid colour comes from the attribute system, not from drawing pixels.
Code
10 REM Progress bar
20 REM Pattern: reusable across games
30 REM
40 REM Usage:
50 REM LET v=75: LET vm=100: GO SUB 2200
60 REM
70 REM Parameters:
80 REM v = current value
90 REM vm = maximum value
100 REM
110 REM Draws a 28-cell horizontal bar at row br
120 REM Colour shifts: blue -> yellow -> red -> white
130 REM Set br before first call (default row 15)
140 REM
150 REM Example: temperature bar
160 REM LET br=15: LET v=100-ABS(guess-target)
170 REM LET vm=100: GO SUB 2200
180 REM
2200 REM === Progress bar ===
2210 LET h=INT (v*28/vm)
2220 IF h>28 THEN LET h=28
2230 IF h<0 THEN LET h=0
2240 FOR i=1 TO 28
2250 IF i>h THEN PRINT AT br,1+i; PAPER 0;" ": GO TO 2300
2260 IF i<=9 THEN PRINT AT br,1+i; PAPER 1;" "
2270 IF i>9 AND i<=18 THEN PRINT AT br,1+i; PAPER 6;" "
2280 IF i>18 AND i<=24 THEN PRINT AT br,1+i; PAPER 2;" "
2290 IF i>24 THEN PRINT AT br,1+i; PAPER 7;" "
2300 NEXT i
2310 RETURN
Trade-offs
| Aspect | Detail |
|---|---|
| Speed | 28 PRINT AT calls maximum — fast enough for per-guess updates |
| Memory | ~12 lines of code |
| Limitation | Fixed at 28 cells wide. Adjust thresholds for different ranges |
| Visual | Character-cell resolution (8px blocks). Chunky but readable |
When to use: Any value that benefits from spatial display — health, distance, time remaining.
When to avoid: Values that change every frame — 28 PRINT AT calls per frame is too slow for real-time.
Related
Patterns: Seven-Segment Digits, Attribute Writing (assembly)
Vault: ULA — attribute memory layout | ZX Spectrum