This commit is contained in:
2026-07-18 18:46:43 +02:00
parent e9c69864f1
commit 84e856c5eb
11 changed files with 555 additions and 58 deletions
+19 -7
View File
@@ -1,7 +1,7 @@
# labyrinth
# labyrinth (LabyrinTwo)
Two-player maze duel for the Commodore 64 (ACME + VICE), in the same
spirit as [rabbitc64](../rabbitc64).
**LabyrinTwo** - a two-player maze duel for the Commodore 64
(ACME + VICE), in the same spirit as [rabbitc64](../rabbitc64).
A fresh maze is carved every round on a 39x23 lattice where the walls
are exactly as wide as the corridors. **Player 1** (joystick 2, or
@@ -12,10 +12,19 @@ fire (or `return`) spins the four wall pieces around the cursor by
90 degrees, reshaping the maze in real time. A spin is denied while
anyone is standing in one of the four slots.
The options screen adds two optional twists:
- **runner gun** - player 1 shoots a bullet with fire/`space`; a hit
enemy respawns on a random cell after a pause.
- **spin cooldown** - each spin starts a recharge; further spins are
denied until the draining bar on the status row runs out and the
readout flips back from *wait* to *ready* (the cursor also dims
while recharging).
Screens: TTG intro (ported from rabbitc64) -> main menu
(play / rules / controls / credits) -> game -> win (back to the menu)
or game over (fire retries with a fresh maze, `m` backs out to the
menu).
(play / options / rules / controls / credits) -> game -> win (back
to the menu) or game over (fire retries with a fresh maze, `m` backs
out to the menu).
## Build & run
@@ -29,7 +38,9 @@ Test builds can boot straight into one state:
```
acme -DAUTOPLAY=1 -f cbm -o labyrinth.prg main.asm
# also: AUTORULES, AUTOCONTROLS, AUTOCREDITS, AUTOWIN, AUTOLOSE
# also: AUTOOPTIONS, AUTORULES, AUTOCONTROLS, AUTOCREDITS,
# AUTOWIN, AUTOLOSE; add -DFORCEOPTS=1 to start with both
# options turned on
```
## Files
@@ -38,6 +49,7 @@ acme -DAUTOPLAY=1 -f cbm -o labyrinth.prg main.asm
- `defs.asm` - registers, constants, zero page, macros
- `intro.asm` - TTG boot logo with the gold color wash
- `menu.asm` - main menu card
- `options.asm` - the optional extras and their toggle screen
- `rules.asm` - how to play
- `controls.asm` - joystick + keyboard mappings
- `credits.asm` - the crew
+3 -1
View File
@@ -357,7 +357,9 @@ bigmap: ; screen code (a=1..z=26) -> glyph index
!byte 20, 18, 21, 0, 15, 0 ; u-z
; ---- shared texts (screen codes) ----
txt_title: !scr "labyrinth"
; the title is split so the two words can wear two colors
txt_t1: !scr "labyrin"
txt_t2: !scr "two"
txt_ttgname: !scr "teletype games"
txt_presents:!scr "presents"
txt_return: !scr "fire = return"
+3
View File
@@ -10,6 +10,7 @@ controls_init:
+prtext 8, 9, LGREEN, txt_c1, txt_c1e-txt_c1
+prtext 10, 6, WHITE, txt_c2, txt_c2e-txt_c2
+prtext 11, 6, LGREY, txt_c2b, txt_c2be-txt_c2b
+prtext 13, 6, LBLUE, txt_c3, txt_c3e-txt_c3
+prtext 15, 6, WHITE, txt_c4, txt_c4e-txt_c4
@@ -42,6 +43,8 @@ txt_c1: !scr "player 1 - the runner"
txt_c1e:
txt_c2: !scr "move: joystick 2 or w a s d"
txt_c2e:
txt_c2b: !scr "gun: fire or space, if enabled"
txt_c2be:
txt_c3: !scr "player 2 - the wall spinner"
txt_c3e:
txt_c4: !scr "move: joystick 1 or i j k l"
+6 -1
View File
@@ -31,7 +31,9 @@ SFX_ROTATE = 2 ; wall spin: noise whoosh
SFX_DENY = 3 ; blocked spin: low buzz
SFX_WIN = 4 ; escape: rising jingle
SFX_LOSE = 5 ; caught: descending sweep
NSFX = 6
SFX_SHOT = 6 ; gun fired: short high tick
SFX_HIT = 7 ; enemy hit: noise burst
NSFX = 8
; ---- colors ----
BLACK = 0
@@ -74,6 +76,7 @@ CH_FLOOR = $20 ; space: corridor
CH_EXIT = $5a ; diamond: the goal
CH_PLAYER = $51 ; filled ball: the runner
CH_ENEMY = $57 ; open circle: an enemy
CH_SHOT = $2a ; asterisk: the runner's bullet
COL_WALL = MGREY ; spinnable wall pieces
COL_POST = DGREY ; fixed pivot posts
@@ -84,6 +87,8 @@ REP_HOLD = 10 ; runner: frames before a held dir repeats
REP_PERIOD = 5 ; runner: frames between repeat steps
CREP_HOLD = 12 ; cursor: same, a touch slower
CREP_PERIOD = 7
COOL_TIME = 160 ; spin cooldown option: recharge frames
RESPAWN_TIME = 150 ; gun option: frames until a hit enemy returns
RAS_SYNC = 251 ; raster line polled for the frame sync
; ---- zero page pointers (same slots as rabbitc64) ----
+8 -2
View File
@@ -1,5 +1,5 @@
; -----------------------------------------------------------
; main.asm - LABYRINTH for the C64
; main.asm - LABYRINTWO for the C64
; two-player maze duel: player 1 runs the corridors toward
; the green diamond exit while dodging the roaming colored
; enemies; player 2 rides the wall corners with a cursor
@@ -9,7 +9,8 @@
; Files:
; defs.asm - constants, zero page, macros
; intro.asm - TTG boot logo (ported from rabbitc64)
; menu.asm - main menu: play / rules / credits
; menu.asm - main menu: play / options / rules / ...
; options.asm - optional extras: runner gun, spin cooldown
; rules.asm - how to play
; controls.asm- joystick + keyboard mappings
; credits.asm - the crew (content from rabbitc64, new look)
@@ -57,6 +58,9 @@ start:
!ifdef AUTOCONTROLS {
jsr controls_init
} else {
!ifdef AUTOOPTIONS {
jsr options_init
} else {
!ifdef AUTOCREDITS {
jsr credits_init
} else {
@@ -73,6 +77,7 @@ start:
}
}
}
}
; ============================================================
; main loop - one state update per PAL frame, synced to the
@@ -106,6 +111,7 @@ wf_hit:
; ============================================================
!src "intro.asm"
!src "menu.asm"
!src "options.asm"
!src "rules.asm"
!src "controls.asm"
!src "credits.asm"
+57 -21
View File
@@ -1,16 +1,18 @@
; -----------------------------------------------------------
; menu.asm - full-screen menu card: big LABYRINTH title with
; the gold wash, and a four-item menu: play / rules /
; menu.asm - full-screen menu card: big LABYRINTWO title in
; two colors (gold wash on LABYRIN, cool blue shimmer on
; TWO), and a five-item menu: play / options / rules /
; controls / credits (joystick or w/s up/down + fire, space
; or return)
; -----------------------------------------------------------
MENU_ITEMS = 4
MENU_ITEMS = 5
menu_init:
jsr clear_screen
+prbig 2, 2, YELLOW, txt_title, 9
+prbig 2, 0, YELLOW, txt_t1, 7
+prbig 2, 28, CYAN, txt_t2, 3
+prtext 9, 13, LGREY, txt_ttgname, 14
lda #0
@@ -21,7 +23,8 @@ menu_init:
rts
menu_update:
; gold wash rolling down the big title (rows 2-6)
; the title rows 2-6: gold wash on LABYRIN (columns 0-26),
; cool blue shimmer on TWO (columns 27-38)
inc washphase
lda #0
sta g8row
@@ -39,7 +42,7 @@ mw_row:
tax
lda washtbl,x
sta rtmp
ldy #37 ; the title spans columns 2-36
ldy #26
mw_col:
lda (scrlo),y
cmp #$a0 ; only touch the letter blocks
@@ -48,8 +51,26 @@ mw_col:
sta (collo),y
mw_skip:
dey
cpy #1
bne mw_col
bpl mw_col
lda washphase
lsr
clc
adc g8row
and #7
tax
lda cooltbl,x
sta rtmp
ldy #38
mw_col2:
lda (scrlo),y
cmp #$a0
bne mw_skip2
lda rtmp
sta (collo),y
mw_skip2:
dey
cpy #26
bne mw_col2
inc g8row
lda g8row
cmp #5
@@ -104,10 +125,11 @@ mm_items:
; blinking '>' cursor in front of the picked line
lda #$20
sta SCREEN+12*40+15
sta SCREEN+14*40+15
sta SCREEN+16*40+15
sta SCREEN+18*40+15
sta SCREEN+11*40+15
sta SCREEN+13*40+15
sta SCREEN+15*40+15
sta SCREEN+17*40+15
sta SCREEN+19*40+15
lda framectr
and #16
bne mu_start
@@ -135,12 +157,16 @@ mu_start:
lda menusel
beq mg_play
cmp #1
beq mg_rules
beq mg_options
cmp #2
beq mg_rules
cmp #3
beq mg_controls
jmp credits_init ; each init's rts returns to the main loop
mg_play:
jmp play_init
mg_options:
jmp options_init
mg_rules:
jmp rules_init
mg_controls:
@@ -169,19 +195,29 @@ dm_store:
jmp print_text
; ---- menu tables ----
mitem_lo: !byte <txt_play, <txt_rules, <txt_controls, <txt_credits
mitem_hi: !byte >txt_play, >txt_rules, >txt_controls, >txt_credits
mitem_len: !byte 4, 5, 8, 7
mitem_row: !byte 12, 14, 16, 18
mitem_lo:
!byte <txt_play, <txt_options, <txt_rules
!byte <txt_controls, <txt_credits
mitem_hi:
!byte >txt_play, >txt_options, >txt_rules
!byte >txt_controls, >txt_credits
mitem_len: !byte 4, 7, 5, 8, 7
mitem_row: !byte 11, 13, 15, 17, 19
mcur_lo: ; cursor cells: column 15 of those rows
!byte <(SCREEN+12*40+15), <(SCREEN+14*40+15)
!byte <(SCREEN+16*40+15), <(SCREEN+18*40+15)
!byte <(SCREEN+11*40+15), <(SCREEN+13*40+15)
!byte <(SCREEN+15*40+15), <(SCREEN+17*40+15)
!byte <(SCREEN+19*40+15)
mcur_hi:
!byte >(SCREEN+12*40+15), >(SCREEN+14*40+15)
!byte >(SCREEN+16*40+15), >(SCREEN+18*40+15)
!byte >(SCREEN+11*40+15), >(SCREEN+13*40+15)
!byte >(SCREEN+15*40+15), >(SCREEN+17*40+15)
!byte >(SCREEN+19*40+15)
cooltbl: ; blue-cyan-white shimmer for the TWO
!byte $06, $0e, $03, $01, $01, $03, $0e, $06
; ---- menu texts ----
txt_play: !scr "play"
txt_options: !scr "options"
txt_rules: !scr "rules"
txt_credits: !scr "credits"
txt_info: !scr "p1: joy2 / wasd - runner"
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "labyrinth",
"title": "Labyrinth",
"title": "LabyrinTwo",
"author": "Teletype Games",
"desc": "Two-player maze duel: one player runs for the exit while the other spins the walls of the labyrinth around their corners. Dodge the enemies, find the diamond.",
"site": "https://git.teletype.hu/games/labyrinth",
+194
View File
@@ -0,0 +1,194 @@
; -----------------------------------------------------------
; options.asm - optional extras, toggled with fire:
; runner gun - player 1 shoots with fire; a hit enemy
; respawns elsewhere after a pause
; spin cooldown - the wall spinner needs a recharge between
; two spins, shown on the status row
; the settings live here and survive between rounds
; -----------------------------------------------------------
OPT_ITEMS = 3
options_init:
jsr clear_screen
+prbig 1, 6, WHITE, txt_options, 7
+prtext 19, 6, LGREY, txt_oh1, txt_oh1e-txt_oh1
+prtext 20, 4, LGREY, txt_oh2, txt_oh2e-txt_oh2
lda #0
sta optsel
+setupd options_update
rts
options_update:
; joystick / w-s steps the cursor (edge detected)
jsr read_joy
lda joyb
and #3
beq ou_udrel
lda udheld
bne ou_udend
lda #1
sta udheld
lda joyb
and #1 ; up
beq ou_down
lda optsel
beq ou_udend
dec optsel
lda #SFX_CURSOR
jsr sfx_play
jmp ou_udend
ou_down:
lda optsel
cmp #OPT_ITEMS-1
beq ou_udend
inc optsel
lda #SFX_CURSOR
jsr sfx_play
jmp ou_udend
ou_udrel:
lda #0
sta udheld
ou_udend:
; the three lines, the picked one in yellow
ldx #0
oo_items:
txa
pha
jsr draw_oitem
pla
tax
inx
cpx #OPT_ITEMS
bne oo_items
; the current values next to the two settings
ldx opt_shoot
lda #10
jsr put_oval
ldx opt_cool
lda #13
jsr put_oval
; blinking '>' cursor in front of the picked line
lda #$20
sta SCREEN+10*40+7
sta SCREEN+13*40+7
sta SCREEN+16*40+7
lda framectr
and #16
bne ou_fire
ldx optsel
lda ocur_lo,x
sta scrlo
lda ocur_hi,x
sta scrhi
ldy #0
lda #62 ; '>'
sta (scrlo),y
lda scrhi
clc
adc #$d4 ; same cell in color RAM
sta scrhi
lda #YELLOW
sta (scrlo),y
ou_fire:
; fire toggles the picked setting / leaves on back
jsr start_edge
beq ou_done
lda optsel
cmp #2
beq ou_back
cmp #1
beq ou_tcool
lda opt_shoot
eor #1
sta opt_shoot
jmp ou_tsfx
ou_tcool:
lda opt_cool
eor #1
sta opt_cool
ou_tsfx:
lda #SFX_SELECT
jsr sfx_play
ou_done:
rts
ou_back:
lda #SFX_SELECT
jsr sfx_play
jmp menu_init
; ---- draw option line X, yellow when it is the picked one ----
draw_oitem:
lda oitem_lo,x
sta txtlo
lda oitem_hi,x
sta txthi
lda oitem_row,x
sta prow
lda #9
sta pcol
lda oitem_len,x
sta plen
lda #WHITE
cpx optsel
bne do_store
lda #YELLOW
do_store:
sta pcolor
jmp print_text
; ---- print the on/off value: X = 0/1, A = screen row ----
put_oval:
sta prow
lda ovtx_lo,x
sta txtlo
lda ovtx_hi,x
sta txthi
lda ovcol,x
sta pcolor
lda #24
sta pcol
lda #3
sta plen
jmp print_text
; ---- option tables ----
oitem_lo: !byte <txt_ogun, <txt_ocool, <txt_oback
oitem_hi: !byte >txt_ogun, >txt_ocool, >txt_oback
oitem_len: !byte 10, 13, 4
oitem_row: !byte 10, 13, 16
ocur_lo: ; cursor cells: column 7 of those rows
!byte <(SCREEN+10*40+7), <(SCREEN+13*40+7), <(SCREEN+16*40+7)
ocur_hi:
!byte >(SCREEN+10*40+7), >(SCREEN+13*40+7), >(SCREEN+16*40+7)
ovtx_lo: !byte <txt_off, <txt_on
ovtx_hi: !byte >txt_off, >txt_on
ovcol: !byte LGREY, LGREEN
; ---- option texts ----
txt_ogun: !scr "runner gun"
txt_ocool: !scr "spin cooldown"
txt_oback: !scr "back"
txt_on: !scr "on "
txt_off: !scr "off"
txt_oh1: !scr "gun: p1 fire shoots a bullet"
txt_oh1e:
txt_oh2: !scr "cooldown: spins need a recharge"
txt_oh2e:
; ---- the settings themselves (session-wide) ----
!ifdef FORCEOPTS { ; test builds start with both turned on
opt_shoot: !byte 1
opt_cool: !byte 1
} else {
opt_shoot: !byte 0 ; 0 = classic game, 1 = the runner shoots
opt_cool: !byte 0 ; 1 = spins need a recharge
}
optsel: !byte 0 ; picked line: 0-2
+252 -14
View File
@@ -6,6 +6,14 @@
; four wall pieces around the cursor by 90 degrees; the
; roaming colored enemies end the round on touch
;
; optional extras (see options.asm):
; opt_shoot - player 1's fire shoots a bullet in the last
; direction faced; a hit enemy respawns on a
; random cell after RESPAWN_TIME frames
; opt_cool - a spin starts a COOL_TIME recharge, shown as
; a draining bar on the status row; spins are
; denied (buzz) until it runs out
;
; screen layout: status on row 0, the 39x23 maze lattice on
; rows 1-23 (cells = odd col / even row, posts = even col /
; odd row, wall slots = the rest), a hint line on row 24
@@ -13,7 +21,8 @@
play_init:
jsr clear_screen
+prtext 0, 0, WHITE, txt_title, 9
+prtext 0, 0, WHITE, txt_t1, 7
+prtext 0, 7, CYAN, txt_t2, 3
+prtext 0, 28, LGREY, txt_goal, txt_goale-txt_goal
+prtext 24, 6, DGREY, txt_hint, txt_hinte-txt_hint
@@ -81,11 +90,14 @@ pi_exit:
lda #COL_EXIT
sta (collo),y
; the runner starts in the top-left cell
; the runner starts in the top-left cell, facing right
lda #1
sta px
sta fdx
lda #2
sta py
lda #0
sta fdy
jsr draw_player
; the corner cursor starts on the center post
@@ -96,14 +108,17 @@ pi_exit:
jsr spawn_enemies
; input state: a fire still held from the previous screen
; must be released before it can spin walls
; input state: fire still held from the previous screen
; must be released before it can spin or shoot
lda #0
sta rheld
sta cheld
sta endflag
sta s_on
sta cool
lda #1
sta cfheld
sta rfheld
+setupd play_update
rts
@@ -260,7 +275,15 @@ mul19: !byte 0, 19, 38, 57, 76, 95, 114, 133, 152, 171, 190
spawn_enemies:
lda #0
sta ei
sn_loop:
sn_all:
jsr spawn_one
inc ei
lda ei
cmp #NENEMIES
bne sn_all
rts
spawn_one: ; place enemy ei on a random free cell
sn_rx:
jsr rand8
and #$0f
@@ -303,10 +326,8 @@ sn_ry:
jsr rand8
and #3
sta edir,x
inc ei
lda ei
cmp #NENEMIES
bne sn_loop
lda #0
sta edead,x
rts
ecoltab: ; anything but the white runner / grey walls
@@ -316,14 +337,20 @@ ecoltab: ; anything but the white runner / grey walls
; one frame of play
; ============================================================
play_update:
lda cool ; the spin recharge ticks down
beq pu_nocool
dec cool
pu_nocool:
jsr upd_runner
lda endflag
bne pu_end
jsr upd_shot
jsr upd_enemies
lda endflag
bne pu_end
jsr upd_cursor
jsr upd_flash
jsr upd_status
rts
pu_end:
cmp #1
@@ -361,6 +388,7 @@ ur_first:
lda #REP_HOLD
sta rtimer
ur_move:
; decode the direction; it also becomes the gun's facing
ldx px
ldy py
lda rdir
@@ -371,15 +399,31 @@ ur_move:
lsr
bcs ur_left
inx ; right
lda #1
sta fdx
lda #0
sta fdy
jmp ur_try
ur_up:
dey
lda #0
sta fdx
lda #$ff
sta fdy
jmp ur_try
ur_down:
iny
lda #0
sta fdx
lda #1
sta fdy
jmp ur_try
ur_left:
dex
lda #$ff
sta fdx
lda #0
sta fdy
ur_try:
stx ttx
sty tty
@@ -393,7 +437,7 @@ ur_try:
beq ur_win
cmp #CH_ENEMY
beq ur_dead
rts ; a wall: blocked
rts ; a wall (or the bullet): blocked
ur_go:
ldx py
jsr row_ptr
@@ -426,6 +470,111 @@ draw_player:
sta (collo),y
rts
; ---- the optional gun: one straight-flying bullet ----
upd_shot:
lda s_on
beq sh_nofly
ldx sy ; wipe the bullet from its old spot -
jsr row_ptr ; but only if it is really there: right
ldy sx ; after firing this is the runner's own
lda (scrlo),y ; cell, and the runner must stay drawn
cmp #CH_SHOT
bne sh_step
lda #CH_FLOOR
sta (scrlo),y
lda #BLACK
sta (collo),y
sh_step:
lda sx ; one step along its heading
clc
adc sdx
sta ttx
lda sy
clc
adc sdy
sta tty
ldx tty
jsr row_ptr
ldy ttx
lda (scrlo),y
cmp #CH_FLOOR
beq sh_fly
cmp #CH_ENEMY
beq sh_hit
lda #0 ; a wall (or anything else) stops it
sta s_on
jmp sh_nofly
sh_fly:
lda ttx
sta sx
lda tty
sta sy
lda #CH_SHOT
sta (scrlo),y
lda #YELLOW
sta (collo),y
jmp sh_nofly
sh_hit:
lda #0
sta s_on
jsr kill_enemy ; scrlo/y still point at the victim
sh_nofly:
lda opt_shoot ; fire spawns a bullet (edge detected)
beq sh_done
lda joyb ; read_joy ran in upd_runner this frame
and #JOY_FIRE
beq sh_frel
lda rfheld
bne sh_done
lda #1
sta rfheld
lda s_on
bne sh_done ; one bullet at a time
lda px
sta sx
lda py
sta sy
lda fdx
sta sdx
lda fdy
sta sdy
lda #1
sta s_on
lda #SFX_SHOT
jmp sfx_play
sh_frel:
lda #0
sta rfheld
sh_done:
rts
; ---- the bullet found an enemy at (ttx, tty): it starts its
; respawn timer; the caller's scrlo/y still address its cell ----
kill_enemy:
ldx #0
ke_loop:
lda edead,x
bne ke_next
lda ex,x
cmp ttx
bne ke_next
lda ey,x
cmp tty
bne ke_next
lda #RESPAWN_TIME
sta edead,x
lda #CH_FLOOR
sta (scrlo),y
lda #BLACK
sta (collo),y
lda #SFX_HIT
jmp sfx_play
ke_next:
inx
cpx #NENEMIES
bne ke_loop
rts
; ---- player 2: the corner cursor + the wall spin ----
upd_cursor:
jsr read_joy2
@@ -513,8 +662,16 @@ uc_done:
rts
; ---- spin the four wall slots around post (kx, ky) by 90
; degrees clockwise; denied while anyone stands in them ----
; degrees clockwise; denied while anyone stands in them or
; while the optional cooldown is still recharging ----
do_rotate:
lda opt_cool
beq dr_ready
lda cool
beq dr_ready
lda #SFX_DENY ; still recharging
jmp sfx_play
dr_ready:
ldx ky ; gather the four slot chars
dex
jsr row_ptr
@@ -573,6 +730,11 @@ do_rotate:
iny
lda nch
jsr put_slot
lda opt_cool ; the spin starts the recharge
beq dr_nocool
lda #COOL_TIME
sta cool
dr_nocool:
lda #SFX_ROTATE
jmp sfx_play
rot_deny:
@@ -608,6 +770,13 @@ upd_enemies:
sta ei
ue_loop:
ldx ei
lda edead,x
beq ue_alive
dec edead,x ; shot down: waiting to respawn
bne ue_next
jsr spawn_one ; the timer ran out: back on a fresh cell
jmp ue_next
ue_alive:
lda framectr
clc
adc estag,x
@@ -667,7 +836,7 @@ etry_dir: ; A = direction; C clear when it moved (or won)
beq ed_move
cmp #CH_PLAYER
beq ed_kill
sec ; wall, exit or another enemy: blocked
sec ; wall, exit, bullet or another enemy
rts
ed_kill:
lda #2
@@ -704,7 +873,8 @@ ed_move:
clc
rts
; ---- per-frame flashes: the exit blinks, the cursor pulses ----
; ---- per-frame flashes: the exit blinks; the cursor pulses
; yellow-red, dimmed to grey-red while the spin recharges ----
upd_flash:
ldx exrow
jsr row_ptr
@@ -721,7 +891,20 @@ uf_exset:
ldx ky
jsr row_ptr
ldy kx
lda framectr
lda opt_cool
beq uf_hot
lda cool
beq uf_hot
lda framectr ; recharging: dimmed pulse
and #4
bne uf_cdred
lda #DGREY
jmp uf_cset
uf_cdred:
lda #RED
jmp uf_cset
uf_hot:
lda framectr ; ready: bright pulse
and #4
bne uf_cred
lda #YELLOW
@@ -732,23 +915,77 @@ uf_cset:
sta (collo),y
rts
; ---- status row: the spin recharge readout (cooldown option)
; "wait" + a draining bar while recharging, "ready" after ----
upd_status:
lda opt_cool
bne us_show
rts
us_show:
lda cool
beq us_ready
+prtext 0, 12, LRED, txt_wait, 4
lda cool ; blocks left: (cool + 15) / 16 = 1-10
clc
adc #15
lsr
lsr
lsr
lsr
sta ptmp
ldx #9
us_bar:
cpx ptmp
bcc us_blk ; x < blocks: still filled
lda #$20
jmp us_put
us_blk:
lda #$a0
us_put:
sta SCREEN+18,x ; bar cells: row 0, columns 18-27
lda #LRED
sta COLRAM+18,x
dex
bpl us_bar
rts
us_ready:
+prtext 0, 12, LGREEN, txt_ready, 5
lda #$20 ; clear the bar area
ldx #9
us_clr:
sta SCREEN+18,x
dex
bpl us_clr
rts
; ---- play texts ----
txt_goal: !scr "reach the "
!byte CH_EXIT
txt_goale:
txt_hint: !scr "p1: joy2/wasd p2: joy1/ijkl"
txt_hinte:
txt_wait: !scr "wait"
txt_ready: !scr "ready"
; ---- play variables ----
px: !byte 0 ; runner position (screen col / row)
py: !byte 0
fdx: !byte 0 ; runner facing: the gun aims this way
fdy: !byte 0
kx: !byte 0 ; corner cursor position (post col / row)
ky: !byte 0
exrow: !byte 0 ; screen row of the exit diamond
endflag: !byte 0 ; 0 = playing, 1 = escaped, 2 = caught
cool: !byte 0 ; spin recharge frames left (cooldown option)
s_on: !byte 0 ; bullet in flight?
sx: !byte 0 ; bullet position and heading
sy: !byte 0
sdx: !byte 0
sdy: !byte 0
rheld: !byte 0 ; runner direction repeat state
rtimer: !byte 0
rdir: !byte 0
rfheld: !byte 0 ; runner fire edge detection state
cheld: !byte 0 ; cursor direction repeat state
ctimer: !byte 0
cdir: !byte 0
@@ -776,6 +1013,7 @@ ex: !fill NENEMIES, 0 ; enemy positions, headings, colors
ey: !fill NENEMIES, 0
edir: !fill NENEMIES, 0
ecol: !fill NENEMIES, 0
edead: !fill NENEMIES, 0 ; respawn countdown, 0 = alive
; ---- maze generator buffers ----
visited: !fill NCELLS, 0
+7 -6
View File
@@ -57,12 +57,13 @@ su_slide:
su_idle:
rts
; ---- effect tables: cursor, select, rotate, deny, win, lose ----
sfxfreq: !byte $50, $20, $12, $06, $20, $38
sfxslide: !byte $00, $04, $fe, $00, $02, $ff
sfxctrl: !byte $11, $21, $81, $21, $11, $21
sfxad: !byte $06, $08, $08, $08, $0a, $0a
sfxdur: !byte $04, $0a, $08, $0c, $28, $30
; ---- effect tables:
; cursor, select, rotate, deny, win, lose, shot, hit ----
sfxfreq: !byte $50, $20, $12, $06, $20, $38, $60, $40
sfxslide: !byte $00, $04, $fe, $00, $02, $ff, $fa, $fc
sfxctrl: !byte $11, $21, $81, $21, $11, $21, $11, $81
sfxad: !byte $06, $08, $08, $08, $0a, $0a, $05, $08
sfxdur: !byte $04, $0a, $08, $0c, $28, $30, $03, $08
; ---- driver variables ----
sfx_timer: !byte 0 ; frames left of the current effect
+2 -2
View File
@@ -9,7 +9,7 @@ win_init:
+prbig 3, 6, YELLOW, txt_escaped, 7
+prtext 11, 15, WHITE, txt_welldone, txt_welldonee-txt_welldone
+prtext 13, 9, LGREY, txt_beaten, txt_beatene-txt_beaten
+prtext 13, 10, LGREY, txt_beaten, txt_beatene-txt_beaten
lda #0
sta washphase
@@ -70,7 +70,7 @@ wu_stay:
txt_escaped: !scr "escaped"
txt_welldone: !scr "well done!"
txt_welldonee:
txt_beaten: !scr "you beat the labyrinth"
txt_beaten: !scr "you beat labyrintwo"
txt_beatene:
txt_firemenu: !scr "fire = menu"
txt_firemenue: