Skip to content

Progress Bar (BASIC)

Horizontal progress bar coloured like a gauge — red when low, yellow in the middle, green when high. Useful for fuel, health or time left.

Illustration of the 28-cell BASIC bar, from empty to full. Colours follow the listing; this is not an emulator capture.

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:

BASIC
10 LET br=15: LET v=50: LET vm=100
20 GO SUB 2200
30 STOP

The 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

progress-bar.bas
  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 RETURN

Trade-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.

Patterns: Seven-Segment Digits, Attribute Writing (assembly)

Vault: ULA — attribute memory layout | ZX Spectrum