Code status: maintained BASIC subroutine. The source listing is included below. Supply the caller and inputs described here before using it. ROM-loaded standalone checks now cover the declared display footprint.
Audit execution record · Scope and remaining checks
Overview
A 28-cell horizontal bar that fills proportionally to a value. The whole bar takes one colour from how full it is: red when low, yellow in the middle, green when high. Uses PRINT AT with PAPER colours. Ideal for fuel gauges, health bars, timer displays, or any value shown spatially rather than numerically.
Calling the routine
This is a subroutine for a Sinclair BASIC program, not a complete program to run on its own. Set these variables before calling GO SUB 2200:
| Input | Contract |
|---|---|
v |
Current numeric value; values below zero or above the maximum are clamped |
vm |
Maximum value; must be greater than zero |
br |
Screen row, from 0 to 21; there is no default in the code |
For example, after adding the routine to your program:
10 LET br=15: LET v=50: LET vm=100
20 GO SUB 2200
30 STOPThe routine writes columns 2–29 on row br and changes h, i and c. Reserve those variables and that screen area, or rename them to suit your program. Call it again after changing v; it clears cells that are no longer filled.
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.
Because INT rounds down, a cell lights only once the value covers its whole share: the first cell needs at least vm/28. The bar is red while 9 or fewer cells are lit, yellow from 10 to 18 and green from 19 to 28; unlit cells are printed with black paper, so a falling value clears the cells it no longer reaches.
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 br=15: 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 One colour for the whole bar: red when low,
125 REM yellow in the middle, green when high
130 REM Set br before first call (for example, 15)
140 REM
150 REM Example: closeness 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 LET c=4: IF h<19 THEN LET c=6
2250 IF h<10 THEN LET c=2
2260 FOR i=1 TO 28
2270 IF i>h THEN PRINT AT br,1+i; PAPER 0;" ": GO TO 2290
2280 PRINT AT br,1+i; PAPER c;" "
2290 NEXT i
2300 RETURNTrade-offs
| Aspect | Detail |
|---|---|
| Speed | 28 PRINT AT calls maximum — fast enough for per-guess updates |
| State | Uses v, vm, br; changes h, i and c |
| 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