--- title: "Star Blast" id: 55977 type: "computer_media" slug: "star-blast" url: "http://localhost/computer_media/star-blast/" markdown_url: "http://localhost/computer_media/star-blast.md" published_at: "2024-07-14T13:17:17+00:00" modified_at: "2026-03-30T21:45:49+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2024/07/star-blaster.jpeg" caption: "Vintage 1980s cassette inlay art, space shooter game, heroic astronaut pilot gripping a massive chrome cannon turret, blasting streams of bright laser bolts into a dense scrolling star field, explosions of orange and yellow light against deep navy space, enemy waves crowding the background in tight formations, dynamic low-angle composition with motion blur on stars, vivid red and electric blue energy beams, futuristic cockpit frame in foreground, early 1980s American sci-fi commercial illustration style, earnest and slightly stiff, rich saturated colors on dark background --ar 3:4 --raw --v 6 Job ID: efc2a366-30db-4f6d-832f-2ff74b27592f" excerpt: "Blast scrolling star fields with a custom-drawn cannon in this joystick-controlled space shooter that gets faster and more crowded with every wave." category: - name: "Archived Media" slug: "archived-media" taxonomy: "category" url: "http://localhost/category/archived-media/" post_tag: - name: "Downloadable" slug: "downloadable" taxonomy: "post_tag" url: "http://localhost/tag/downloadable/" - name: "TS 2068" slug: "ts2068" taxonomy: "post_tag" url: "http://localhost/tag/ts2068/" model: - name: "Timex/Sinclair 2068" slug: "ts-2068" taxonomy: "model" url: "http://localhost/model/ts-2068/" 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: 55923 title: "Timex Sinclair Public Domain Library Tape 2003" type: "computer_media" url: "http://localhost/computer_media/timex-sinclair-public-domain-library-tape-2003/" media_type: "Program" download_url: "https://archive.org/download/timex-sinclair-software-archive/StarBlast%20%28198x%29%28TS2068%29%28US%29%28Program%29.zip" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2024/07/star-blaster.jpeg" caption: "Vintage 1980s cassette inlay art, space shooter game, heroic astronaut pilot gripping a massive chrome cannon turret, blasting streams of bright laser bolts into a dense scrolling star field, explosions of orange and yellow light against deep navy space, enemy waves crowding the background in tight formations, dynamic low-angle composition with motion blur on stars, vivid red and electric blue energy beams, futuristic cockpit frame in foreground, early 1980s American sci-fi commercial illustration style, earnest and slightly stiff, rich saturated colors on dark background --ar 3:4 --raw --v 6 Job ID: efc2a366-30db-4f6d-832f-2ff74b27592f" - url: "http://localhost/wp-content/uploads/2024/07/SCR-20240714-ipgq.png" media_type_tags: "Arcade, Game" --- # Star Blast This program implements a space shooter game where the player controls a cannon (UDG “a”) at the bottom of the screen, firing projectiles (UDG “b”) upward to hit stars (UDG “c”) arranged in four scrolling rows. Three custom UDG characters are defined via POKE USR: a triangular cannon shape, a vertical bullet, and an eight-pointed star. The four rows of stars scroll horizontally at different rates — row k shifts by k characters every 50 timer ticks — creating increasing difficulty. The STICK command (encoded as |) reads joystick input for movement and firing, and the score increments by 100 for each successful hit, with the time limit extending by 500 ticks each wave. *** ## Program Analysis ### Program Structure The program is organized into clearly separated segments by line number range: 1. **200–300:** Initialization — screen clear, variable setup, score label. 2. **500–770:** UDG character definition via `POKE USR`. 3. **900–980:** Wave initialization — star array reset, initial star placement, screen draw. 4. **1010–1310:** Main game loop — joystick polling, player movement, projectile update, timing logic. 5. **3000–3070:** Subroutine: populate star field array. 6. **4000–4030:** Subroutine: render all four star rows to screen. 7. **5000–5080:** Subroutine: scroll star rows. 8. **6000–6130:** Subroutine: collision detection between projectile and stars. 9. **7000–7030:** Subroutine: score update and sound effect. 10. **9000–9020:** End-of-level handler, resets and restarts game. ### UDG Character Definitions Three User-Defined Graphics are created using `POKE USR` and `BIN` literals: | UDG | Purpose | Description | | --- | --- | --- | | `\a` | Cannon / player | Wide triangle shape, narrow top, broad base — resembles a spaceship or cannon barrel. | | `\b` | Projectile / bullet | Thin vertical line with a slight fork at the bottom — a stylized missile. | | `\c` | Star / target | Radiating pattern with a solid cross and diagonal hints — an 8-point star. Note: line 710 contains `BIN 011111110` (9 digits), which the interpreter silently truncates to 8 bits, effectively the same as `BIN 11111110`. | ### Joystick Input via STICK The program uses the TS2068 `STICK` keyword (encoded as `|` in the source). `|(1,1)` polls joystick port 1: a return value of `4` moves the cannon left (line `1010`), `8` moves it right (line `1020`), and `|(2,1)=1` on the second axis triggers a shot (line `1030`). This makes the game entirely joystick-driven with no keyboard fallback. ### Star Field and Scrolling The star field is stored in a 4×32 string array `a$`, where each row corresponds to one of four display rows on screen, each separated by a blank line. The scrolling subroutine at line `5000` rotates row `k` left by `k` characters using string slicing — so row 1 scrolls slowest and row 4 scrolls fastest. This differential scrolling is achieved with: - `h$=a$(k,1 TO k)` — save the leading `k` characters. - `a$(k,1 TO 32-k)=a$(k,k+1 TO 32)` — shift left. - `a$(k,32-k+1 TO )=h$` — wrap saved characters to the end. Scrolling is triggered every 50 timer increments (checked at line `1265` with `IF tm/50=INT(tm/50)`), giving a periodic rather than continuous scroll. ### Projectile and Collision Detection When fired, the projectile starts at row 19, column `sta` (the cannon’s position) and moves up by 2 rows per loop iteration (`LET s=s-2`, line `1250`). Collision is checked only when the projectile is in the upper half of the screen (`s<=7`) and on an odd row (`s/2<>INT(s/2)`), since star rows occupy rows 1, 3, 5, and 7. The subroutine at `6000` checks `a$(k,c+1)="\c"` for each of the four star rows: the column offset of `c+1` is because the array is 1-indexed while screen columns are 0-indexed. A hit clears the array cell, erases the character from the screen, decrements `left`, and adds 100 to the score. ### Wave Progression and Difficulty The variable `n` controls the number of stars placed per wave, initialized to 15 and incremented by 5 each new wave up to a cap of 100 (line `3000`). The time limit `limit` is extended by 500 ticks per wave. The condition at line `1270` (`IF tm=limit`) ends the current wave and loops back to line `200` for a full reset rather than continuing from where the player left off — meaning there is no persistent score accumulation across waves. ### Notable Bugs and Anomalies - Line `1280` checks `IF left=0 THEN GO TO 1300`, but line `1300` is simply `GO TO 1010` — the branch to `1300` is identical in behavior to falling through to line `1290`, which also goes to `1010`. The intent may have been to trigger a new wave when all stars are cleared, but lines `1310`–`1320` (which call `GO SUB 4000` and loop back) are never reached by any execution path. - Line `710` uses `BIN 011111110`, a 9-bit binary literal. The interpreter reads only the rightmost 8 bits, yielding `11111110` (254) instead of the likely intended `01111110` (126). This causes the top of the star UDG to have its leftmost pixel lit unexpectedly. - The projectile column variable is named `c`, which shadows no keyword but is also used without initialization if `pr` is ever non-zero from a prior cycle without a fresh shot — in practice the flow prevents this. ## Source Code ``` 200 DIM a$(4,32) 220 LET n=15 230 LET tm=0 240 LET s$=" " 245 PAPER 1: BRIGHT 1 250 FOR j=0 TO 21 260 PRINT AT j,0;s$;s$ 270 NEXT j 280 LET pr=0 290 INK 7: PRINT AT 21,11;"Score " 300 LET limit=800 500 POKE USR "a",BIN 00011000 510 POKE USR "a"+1,BIN 00011000 520 POKE USR "a"+2,BIN 00111100 530 POKE USR "a"+3,BIN 00111100 540 POKE USR "a"+4,BIN 01111110 550 POKE USR "a"+5,BIN 01100110 560 POKE USR "a"+6,BIN 11000011 570 POKE USR "a"+7,BIN 11000011 600 POKE USR "b",BIN 00011000 610 POKE USR "b"+1,BIN 00011000 620 POKE USR "b"+2,BIN 00011000 630 POKE USR "b"+3,BIN 00011000 640 POKE USR "b"+4,BIN 00011000 650 POKE USR "b"+5,BIN 00011000 660 POKE USR "b"+6,BIN 00100100 670 POKE USR "b"+7,BIN 00000000 700 POKE USR "c",BIN 00000000 710 POKE USR "c"+1,BIN 011111110 720 POKE USR "c"+2,BIN 11111111 730 POKE USR "c"+3,BIN 00011000 740 POKE USR "c"+4,BIN 00111100 750 POKE USR "c"+5,BIN 01111110 760 POKE USR "c"+6,BIN 11111111 770 POKE USR "c"+7,BIN 00011000 900 LET sta=15 910 FOR i=1 TO 4 930 FOR j=1 TO 32 940 LET a$(i,j)=" " 950 NEXT j 960 NEXT i 970 LET scr=0 980 GO SUB 3000 985 GO SUB 4000 1010 IF |(1,1)=4 THEN GO TO 1100 1020 IF |(1,1)=8 THEN GO TO 1150 1030 IF |(2,1)=1 THEN GO TO 1060 1050 GO TO 1200 1060 LET pr=1: LET s=19: LET c=sta 1070 GO TO 1200 1100 IF sta-1<0 THEN GO TO 1200 1110 PRINT AT 20,sta;" " 1120 LET sta=sta-1 1130 GO TO 1200 1150 IF sta+1>31 THEN GO TO 1200 1160 PRINT AT 20,sta;" " 1170 LET sta=sta+1 1180 GO TO 1200 1200 INK 6: PRINT AT 20,sta;"\a" 1210 IF pr=0 THEN GO TO 1260 1220 IF s<=7 AND s/2<>INT (s/2) THEN GO SUB 6000 1230 INK 6: PRINT AT s,c;"\b" 1240 PAUSE 3: PRINT AT s,c;" " 1250 LET s=s-2 1260 LET tm=tm+8 1265 IF tm/50=INT (tm/50) THEN GO SUB 5000 1270 IF tm=limit THEN GO TO 9000 1280 IF left=0 THEN GO TO 1300 1290 GO TO 1010 1300 GO TO 1010 1310 GO SUB 4000 1320 GO TO 1010 3000 IF n<100 THEN LET n=n+5 3005 LET limit=limit+500: LET left=n 3010 FOR k=1 TO n 3020 LET x=INT (RND*4)+1 3030 LET y=INT (RND*32)+1 3040 IF a$(x,y)<>" " THEN GO TO 3020 3050 LET a$(x,y)="\c" 3060 NEXT k 3070 RETURN 4000 FOR k=1 TO 4 4010 INK 7: PRINT AT (k-1)*2+1,0;a$(k,1 TO 32) 4020 NEXT k 4030 RETURN 5000 FOR k=1 TO 4 5010 LET h$=a$(k,1 TO k) 5020 LET a$(k,1 TO 32-k)=a$(k,k+1 TO 32) 5030 LET a$(k,32-k+1 TO )=h$ 5040 NEXT k 5050 GO SUB 4000 5080 RETURN 6000 FOR k=4 TO 1 STEP -1 6010 IF a$(k,c+1)="\c" AND s=(k-1)*2+1 THEN GO TO 6100 6020 NEXT k 6030 IF s>0 THEN RETURN 6040 GO TO 6120 6100 LET a$(k,c+1)=" " 6103 PRINT AT (k-1)*2+1,c;" " 6105 LET left=left-1 6110 LET scr=scr+100 6115 GO SUB 7000 6120 LET pr=0 6130 RETURN 7000 BEEP 0.01,2 7010 PRINT AT 21,17;scr 7020 FLASH 0 7030 RETURN 9000 BRIGHT 0 9010 INK 0 9020 GO TO 200 9997 SAVE "star blast" 9998 STOP ```