--- title: "Breakout" id: 57121 type: "computer_media" slug: "breakout-3" url: "http://localhost/computer_media/breakout-3/" markdown_url: "http://localhost/computer_media/breakout-3.md" published_at: "2024-10-03T23:51:19+00:00" modified_at: "2026-03-30T21:19:47+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2024/10/breakout.jpeg" caption: "Vintage 1982 cassette inlay art, hand-drawn felt-tip marker illustration of a chunky pixel ball smashing through a colorful wall of rectangular bricks, fragments flying, bold simple bat shape at the bottom, dramatic action lines radiating outward, amateur bedroom-coder energy, Letraset rub-down lettering spelling BREAKOUT with slightly uneven letter spacing, flat bold colors on white card stock, limited red yellow and black palette, lo-fi photocopied zine aesthetic, rough handmade DIY illustration style, simple geometric shapes, charming naïve quality --ar 3:4 --raw --v 6 Job ID: 87fcaf4e-33fd-449d-9709-f6f0a7661c78" excerpt: "A brick-busting Breakout game that directly POKEs the display file for smooth bat and ball movement, with block-graphic walls and a persistent high score." category: - name: "Archived Media" slug: "archived-media" taxonomy: "category" url: "http://localhost/category/archived-media/" post_tag: - name: "Best of Timex/Sinclair 1000 Articles and Documents" slug: "ts1000best" taxonomy: "post_tag" url: "http://localhost/tag/ts1000best/" - name: "Downloadable" slug: "downloadable" taxonomy: "post_tag" url: "http://localhost/tag/downloadable/" - name: "TS 1000" slug: "ts1000" taxonomy: "post_tag" url: "http://localhost/tag/ts1000/" model: - name: "Timex/Sinclair 1000" slug: "ts-1000" taxonomy: "model" url: "http://localhost/model/ts-1000/" genre: - name: "Arcade" slug: "arcade" taxonomy: "genre" url: "http://localhost/type/arcade/" - name: "Game" slug: "game" taxonomy: "genre" url: "http://localhost/type/game/" media_contents: - id: 56733 title: "Timex Sinclair Public Domain Library Tape 1002" type: "computer_media" url: "http://localhost/computer_media/timex-sinclair-public-domain-library-tape-1002/" media_type: "Program" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2024/10/breakout.jpeg" caption: "Vintage 1982 cassette inlay art, hand-drawn felt-tip marker illustration of a chunky pixel ball smashing through a colorful wall of rectangular bricks, fragments flying, bold simple bat shape at the bottom, dramatic action lines radiating outward, amateur bedroom-coder energy, Letraset rub-down lettering spelling BREAKOUT with slightly uneven letter spacing, flat bold colors on white card stock, limited red yellow and black palette, lo-fi photocopied zine aesthetic, rough handmade DIY illustration style, simple geometric shapes, charming naïve quality --ar 3:4 --raw --v 6 Job ID: 87fcaf4e-33fd-449d-9709-f6f0a7661c78" - url: "http://localhost/wp-content/uploads/2024/10/70_Brk.png" media_type_tags: "Arcade, Game" --- This is a Breakout clone that uses direct POKE operations into the ZX81 display file to move the ball and bat, rather than relying solely on PRINT/AT statements. The program determines the display-file base address at line 165 using the classic PEEK 16396+PEEK 16397*256+1 formula, then computes character cell offsets using the standard 33-bytes-per-row layout (32 columns plus one NEWLINE byte). Block graphics characters are used to draw the top and bottom walls (lines 40 and 50) and the brick field (line 110), with inverse-video letters spelling “BREAKOUT” embedded in each wall. Bat movement is handled by poking character code 5 (a solid block) to the new position and zeroing the old one, with keys 6 and 7 controlling direction. A high-score variable H persists across games within the same session, and the player is prompted to continue or stop after each ball is lost. *** ## Program Analysis ### Program Structure The program is organised into several logical phases: 1. **Instructions (lines 1–4):** Prints control information and pauses before clearing the screen. 2. **Initialisation (lines 5–25):** Resets score `T`, ball-counter `Z`, round counter `Q`, and ball-number `TB`. 3. **Screen setup (lines 30–120):** Draws the top and bottom walls with embedded inverse-video “BREAKOUT” titles and fills columns 13–30 of rows 2–16 with a brick pattern using block graphics. 4. **Ball loop (lines 130–410):** The core game loop — positions the bat and ball, polls keys, detects collisions, updates the score, and handles ball loss and game-over conditions. 5. **End-of-game (lines 415–470):** Displays “GAME OVER”, optionally updates the high score, and prompts the player to continue or stop. ### Display-File Address Calculation Line 165 computes the base address of the display file: `LET P=PEEK 16396+PEEK 16397*256+1` System variables at addresses 16396–16397 hold the D-FILE pointer (the start of the display file including its leading NEWLINE). Adding 1 skips that leading NEWLINE so that `P` points to the first printable row. Each screen row occupies 33 bytes (32 character columns plus one trailing NEWLINE byte), making the offset formula `P + Y*33 + X` used throughout the program straightforward. ### Direct POKE Rendering Rather than using `PRINT AT` for every animation frame, the game manipulates the display file directly via `POKE`. Key operations include: - `POKE P+R, 5` — draws the bat (character code 5, a solid block) at offset `R`. - `POKE P+R, 0` — erases the bat (character code 0, a space) before moving it. - `POKE Z, 28` — temporarily marks the ball position (character code 28, a small dot/period). - `POKE P+Y*33+X, 0` — erases the ball from its previous position. - `POKE P+647, TB+28` — writes the current ball number into a fixed display-file slot (row 19 area) using an offset of 647 (approximately row 19, column 15). ### Ball and Bat Movement The ball’s horizontal and vertical directions are stored in `A` (±1) and `D` (±1) respectively. Each iteration of the main loop advances the ball by `A` in X and `D` in Y. The bat is stored as a raw display-file offset `R`, initialised to 265. Moving the bat one column left or right changes `R` by ±33, not ±1, which is unusual — it means the bat moves one *row* at a time in the display file rather than one column. This is a bug: `R` should change by ±1 for horizontal movement, not ±33. As written, pressing key 6 or 7 moves the bat diagonally through the display file rather than along a single row, likely causing the bat to appear at unexpected positions or trigger erratic display-file corruption. ### Collision Detection Collision is detected by reading the character code at the ball’s next position with `LET N=PEEK Z` (line 280). The logic is: - If `Y=2` or `Y=16`, the ball has hit the top or bottom boundary, so vertical direction `D` is reversed (line 300). - If `N=5` (bat character) or `X=30` (right wall), horizontal direction `A` is reversed (line 310). - If `N>=132` (a brick graphic), the ball has hit a brick: the score is incremented by `(136-N)*5` (line 360) and `A` is reversed (line 380). This produces varying point values depending on which block-graphic code was struck. ### Computed GOTO Idiom The program uses arithmetic in `GOTO` targets as a conditional branch technique: - `GOTO (TB=6)*210+200` (line 180): jumps to line 210 (skipping the POKE at 200) when the sixth ball is reached; otherwise falls through to line 200. - `GOTO (N<132)*30+360` (line 350): if no brick was hit (`N<132`), jumps to line 30 to redraw and continue; otherwise falls to line 360 to score the brick hit. - `GOTO (X>0)*90+130` (line 390): if the ball is still in play (`X>0`), loops back to line 90 (score display area); otherwise falls to line 130 to reset for a new ball. Note that line 210 does not exist in the listing; the jump from line 180 when `TB=6` targets a non-existent line, which on this platform causes execution to continue at the next higher-numbered line (line 220), effectively skipping the ball-number POKE — a deliberate technique. ### Scoring and Progression Score `T` accumulates across balls within a round. The expression `(136-N)*5` gives a score of 5 × (136 minus the brick’s character code); since brick graphics occupy codes 128–135, scores per brick range from 5 to 40 points. After each ball is lost, line 410 checks whether the score exceeds `2000*Q` (where `Q` is incremented each ball at line 25); if so, the playfield is redrawn, effectively starting a new level. The high score `H` is preserved only for the duration of the session. ### Notable Anomalies | Line | Issue | | --- | --- | | `6` | `LET H=0` is inside the main game flow (after `RAND`), so the high score is reset every time line 5 is reached via `GOTO 5` from a new game. The instructions warn the player to set `H` manually in direct mode to work around this. | | `230/330` | Bat offset `R` changes by `±33` per keypress, which moves one full display-file row rather than one column, likely a bug intended to be `±1`. | | `80` | Uses `PRINT ,,` (two commas) to tab to the third print zone; the ball number field ends with a comma, leaving a dangling separator character in the display. | | `410` | The level-advance condition `T>2000*Q` uses the cumulative score against an ever-growing threshold, so later rounds become progressively harder to advance past. | ## Source Code ``` 1 PRINT "IN THIS GAME OF BREAKOUT, IN ORDER TO START PLAY,SET THE HIGH SCORE COUNTER BY ENTERING IN THE DIRECT MODE,(LET H=0,THEN GOTO 5).AFTER SETTING THE HIGH SCORE COUNTER,TO CONTINUE GOTO 5." 2 PRINT AT 10,2;"YOUR BAT KEYS ARE 6 AND 7" 3 PAUSE 700 4 CLS 5 RAND 6 LET H=0 10 LET T=0 15 LET Z=0 17 LET Q=0 20 LET TB=0 25 LET Q=Q+1 30 LET R=265 40 PRINT AT 1,0;"\..\..\..\..\..\..\..\..\..\..\..%B%R%E%A%K%O%U%T\..\..\..\..\..\..\..\..\..\..\..\.." 50 PRINT AT 17,0;"\''\''\''\''\''\''\''\''\''\''\''%B%R%E%A%K%O%U%T\''\''\''\''\''\''\''\''\''\''\''\''" 80 PRINT ,,"TOTAL 0 BALL NO ," 90 PRINT ,," HIGHEST SCORE ";H 100 FOR I=2 TO 16 110 PRINT AT I,13;"\'.\'.\'.\'. \ :\ :\ : \':\':\': \ :" 120 NEXT I 130 LET A=-1 140 LET D=1 150 LET X=11 160 LET Y=INT (RND*10)+5 165 LET P=PEEK 16396+PEEK 16397*256+1 170 LET TB=TB+1 180 GOTO (TB=6)*210+200 200 POKE P+647,TB+28 220 POKE R+P,0 230 LET R=R+33*(INKEY$="6")-33*(INKEY$="7") 240 POKE P+R,5 250 POKE P+Y*33+X,0 260 LET X=X+A 270 LET Y=Y+D 275 LET Z=P+Y*33+X 280 LET N=PEEK Z 290 POKE Z,28 300 IF Y=2 OR Y=16 THEN LET D=-D 310 IF N=5 OR X=30 THEN LET A=-A 320 POKE P+R,0 330 LET R=R+33*(INKEY$="6")-33*(INKEY$="7") 340 POKE P+R,5 350 GOTO (N<132)*30+360 360 LET T=T+(136-N)*5 370 PRINT AT 19,5;T 380 LET A=-A 390 GOTO (X>0)*90+130 410 IF T>2000*Q THEN GOTO 20 415 PRINT AT 10,3;"GAME OVER" 420 IF T>H THEN LET H=T 440 INPUT A$ 450 IF A$="N" THEN STOP 460 CLS 470 GOTO 10 480 SAVE "1007%0" 490 RUN ```