Firepower

Date: 198x
Type: Program
Platform(s): TS 2068
Tags: Arcade

Firepower is a single-screen shooting gallery game in which the player maneuvers a gun sight around the screen to intercept falling enemy sprites. The player’s turret graphic is built from a 65-character DIM array using CHR$ codes for vertical bars, dashes, and a plus sign to form a crosshair shape. A User Defined Graphic (UDG) is loaded via a DATA statement and POKE loop into the UDG area (USR CHR$ 144) to display the falling target — an oval or bomb shape defined by the byte pattern 0,60,126,126,126,126,60,0. Timing is handled by reading the system frames counter at addresses 23672–23673, converting ticks to seconds by dividing by 60, giving a 60-second countdown. Scoring awards 2 points for a direct hit (same screen position) and 1 point for a near-miss (adjacent cell), detected by comparing linearized screen coordinates.


Program Structure

The program is organized into distinct phases:

  1. Initialization (lines 2–15): UDG data is POKEd, the crosshair string array is constructed, and the screen is set up.
  2. Star field generation (line 20): 50 asterisks are placed at random positions.
  3. Game variable reset (lines 25–45): Score, player position, frame counter, and bomb state are initialized.
  4. Main game loop (lines 100–240): Timer update, score display, bomb movement, player movement, collision detection, and redraw all occur here.
  5. End screen (lines 1000–1010): Game over message with restart prompt.
  6. Data (line 1020): Eight bytes defining the UDG sprite.

UDG Sprite

Line 5 loads 8 bytes from the DATA statement at line 1020 into the UDG slot at USR CHR$ 144, defining a symmetrical oval/bomb shape: 0,60,126,126,126,126,60,0. This is displayed via CHR$ 144 throughout the game. The loop iterates from USR CHR$ 144 to USR CHR$ 144+7, covering all 8 pixel rows of the character.

Crosshair Construction

The player’s gun sight is stored in a 65-character string array a$. Rather than printing individual characters, the array is populated sparsely: position 1 gets CHR$ 73 (pipe/vertical bar), position 32 gets CHR$ 45 (dash), position 33 gets CHR$ 43 (plus), position 34 gets CHR$ 45 (dash), and position 65 gets CHR$ 73. The remaining characters default to spaces, giving a two-row crosshair occupying a 32-wide by 2-row region when printed with AT x,y.

Timing Mechanism

The system’s frame counter is stored across two bytes at addresses 23672 and 23673. Line 100 reads these with PEEK 23673*256 + PEEK 23672 and divides by 60 to convert frames to seconds, storing the result in t1. Line 105 detects when t changes to produce a tick beep and update the displayed time. The POKE statements at line 35 reset this counter to zero at the start of each game.

Bomb Movement Logic

A single bomb is tracked by position variables a (row) and b (column), with a horizontal drift value d set to −1, 0, or 1 randomly. Line 120 spawns a new bomb when b=0 (inactive); line 125 erases the old position (via OVER 1 XOR mode) and advances the bomb down and sideways; line 130 deactivates the bomb if it reaches row 21 or the screen edges.

The character code \{16}\{0} in the conditional at line 120 is an INK 0 color control embedded in the condition check — effectively printing an invisible character or acting as a flag to test b.

Collision Detection

Collision uses linearized screen coordinates. Line 205 computes p = (x+1)*22 + y for the player and p1 = a*22 + b for the bomb. A direct hit (p = p1) awards 2 points and triggers a long beep. Line 215 checks for a near-miss by testing ABS(p-p1) = 1 (same row, adjacent column) or ABS(p-p1) = 22 (adjacent row), awarding 1 point. This uses a column-width of 22 rather than 32 in the linearization, which is a minor inaccuracy but produces a workable approximation.

Player Movement

Lines 220–225 read INKEY$ for keys 5/6/7/8 and compute new coordinates x1 and y1 using Boolean arithmetic — adding or subtracting 1 based on the result of logical comparisons. Boundary checks (x<19, x>0, y<30, y>1) are embedded in the same expressions. Line 230 erases the crosshair at the old position (OVER 1 mode), then lines 235–240 update the position and loop.

Display Technique

OVER 1 is set globally at line 15 and used throughout the main loop. This XOR drawing mode means printing a character twice restores the background, enabling flicker-free movement of both the bomb and the player crosshair without explicitly clearing them. The star field placed at line 20 persists beneath the sprites because OVER 1 toggles pixels rather than overwriting them.

Notable Anomalies

  • The linearization factor of 22 (instead of 32) at line 205 means near-miss detection is slightly off for columns beyond 22, but the hit detection at exact equality is unaffected.
  • Line 205 redraws the UDG at the bomb position after a direct hit (PRINT AT a,b; CHR$ 144), which in OVER 1 mode XORs it again — this may visually leave a ghost, though the bomb variable b is immediately zeroed.
  • The crosshair occupies two rows (65 characters = 2×32 + 1), but only specific positions are non-space, so the printed region looks like a sparse two-row symbol rather than a solid block.

Content

Appears On

Related Products

Related Articles

Related Content

Image Gallery

Source Code

    2 REM "firepower"
    5 FOR j= USR CHR$ 144 TO USR CHR$ 144+7:READ a:POKE j,a:NEXT j
   10 DIM a$(65):LET a$(1)= CHR$ 73:LET a$(32)= CHR$ 45:LET a$(34)= CHR$ 45:LET a$(65)= CHR$ 73
   12 LET a$(33)= CHR$ 43
   15 BORDER 5:PAPER 5:INK 0:OVER 1:CLS 
   20 FOR j=1 TO 50:PRINT AT INT (RND*22), INT (RND*32);"*":NEXT j
   25 LET s=0
   30 LET x=11:LET y=15
   35 POKE 23673,0:POKE 23672,0
   40 LET t=0
   45 LET b=0
  100 LET t1= INT ((PEEK 23673*256+ PEEK 23672)/60)
  105 IF t <>t1 THEN BEEP .01,t:LET t=t1
  110 PRINT AT 0,0; OVER 0;"SCORE ";s,"TIME ";t
  115 IF t >=60 THEN GO TO 1000
  120 IF \{16}\{0} NOT b THEN LET b= INT (RND*31)+1:LET a=1:LET d= INT (RND*3)-1:GO TO 130
  125 PRINT AT a,b; CHR$ 144:LET a=a+1:LET b=b+d
  130 IF a=21 OR b=0 OR b=32 THEN LET b=0:GO TO 200
  135 PRINT AT a,b; INK 6; CHR$ 144
  200 PRINT AT x,y; INK 8;a$
  205 LET p=(x+1)*22+y:LET p1=a*22+b:IF p=p1 THEN BEEP 1,50:LET s=s+2:PRINT AT a,b; CHR$ 144:LET b=0:GO TO 220
  210 IF INKEY$ <>"0" THEN GO TO 220
  215 IF ABS (p-p1)=1 OR ABS (p-p1)=22 THEN BEEP .5,50:LET s=s+1
  220 LET x1=x+(INKEY$="6" AND x<19)-(INKEY$="7" AND x>0)
  225 LET y1=y+(INKEY$="8" AND y<30)-(INKEY$="5" AND y>1)
  230 PRINT AT x,y; INK 8;a$
  235 LET x=x1:LET y=y1
  240 GO TO 100
 1000 PRINT OVER 0; FLASH 1; PAPER 2; INK 7; AT 10,12;"GAME OVER"; FLASH 0; AT 21,5;"PRESS""R"" TO PLAY AGAIN"
 1005 IF INKEY$="r" OR INKEY$="R" THEN RUN 
 1010 GO TO 1005
 1020 DATA 0,60,126,126,126,126,60,0

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

People

No people associated with this content.

Scroll to Top