graphics tweaks
This commit is contained in:
@@ -3,23 +3,30 @@
|
||||
**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
|
||||
`w a s d`) runs the corridors toward the green diamond exit while
|
||||
dodging the roaming colored enemies. **Player 2** (joystick 1, or
|
||||
`i j k l`) rides the corners of the walls with a blinking cursor -
|
||||
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.
|
||||
A fresh maze carves itself on screen at the start of every round on
|
||||
a 39x23 lattice where the walls are exactly as wide as the corridors.
|
||||
**Player 1** (joystick 2, or `w a s d`) runs the corridors toward the
|
||||
green exit portal while dodging the roaming enemies. **Player 2**
|
||||
(joystick 1, or `i j k l`) rides the corners of the walls with a
|
||||
bracket cursor - 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 border
|
||||
blips red); the spun pieces flash white.
|
||||
|
||||
The look: brick walls and bolted pivot posts from a custom RAM
|
||||
charset, every actor (runner, cursor, bullet, enemies) a hardware
|
||||
sprite gliding smoothly between the cells, an animated exit portal,
|
||||
a raster color band behind the status row, and a fade to black
|
||||
between all screens. The menu floats over a dark maze backdrop.
|
||||
|
||||
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).
|
||||
denied until the bar on the status row drains (pixel by pixel) and
|
||||
the readout flips back from *wait* to *ready* (the cursor also
|
||||
turns red while recharging).
|
||||
|
||||
Screens: TTG intro (ported from rabbitc64) -> main menu
|
||||
(play / options / rules / controls / credits) -> game -> win (back
|
||||
@@ -45,15 +52,19 @@ acme -DAUTOPLAY=1 -f cbm -o labyrintwo.prg main.asm
|
||||
|
||||
## Files
|
||||
|
||||
- `main.asm` - entry point, BASIC stub, per-frame state machine
|
||||
- `main.asm` - entry point, BASIC stub, per-frame state machine,
|
||||
the border/status-band raster work
|
||||
- `defs.asm` - registers, constants, zero page, macros
|
||||
- `intro.asm` - TTG boot logo with the gold color wash
|
||||
- `menu.asm` - main menu card
|
||||
- `menu.asm` - main menu card over a dark maze backdrop
|
||||
- `options.asm` - the optional extras and their toggle screen
|
||||
- `rules.asm` - how to play
|
||||
- `controls.asm` - joystick + keyboard mappings
|
||||
- `credits.asm` - the crew
|
||||
- `play.asm` - maze generation (recursive backtracker) + the game
|
||||
- `play.asm` - maze generation (recursive backtracker, animated)
|
||||
+ the game
|
||||
- `win.asm` / `over.asm` - end screens
|
||||
- `common.asm` - shared routines: printing, big block font, input, RNG
|
||||
- `sound.asm` - single-voice SID SFX driver
|
||||
- `gfx.asm` - RAM charset with the custom tiles, the sprite engine,
|
||||
the portal animation and the fade-to-black transition
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@ co_hide:
|
||||
co_input:
|
||||
jsr start_edge
|
||||
beq co_stay
|
||||
jmp menu_init
|
||||
+fadeto menu_init
|
||||
co_stay:
|
||||
rts
|
||||
|
||||
|
||||
+1
-1
@@ -135,7 +135,7 @@ cu_hide:
|
||||
cu_input:
|
||||
jsr start_edge
|
||||
beq cu_stay
|
||||
jmp menu_init ; back to the menu
|
||||
+fadeto menu_init ; back to the menu
|
||||
cu_stay:
|
||||
rts
|
||||
|
||||
|
||||
@@ -9,11 +9,25 @@ BORDER = $d020 ; border color register
|
||||
BG = $d021 ; background color register
|
||||
SCREEN = $0400 ; screen RAM (40x25 chars)
|
||||
COLRAM = $d800 ; color RAM
|
||||
SPR_EN = $d015 ; sprite enable bits (parked at 0)
|
||||
SCRCTL = $d011 ; control 1: raster msb, y-scroll
|
||||
SPR_EN = $d015 ; sprite enable bits
|
||||
SPRX0 = $d000 ; sprite 0 x (x/y pairs go up from here)
|
||||
SPRY0 = $d001 ; sprite 0 y
|
||||
SPRMSB = $d010 ; 9th x position bit of each sprite
|
||||
SPRDBLY = $d017 ; sprite y expand
|
||||
VMCSB = $d018 ; memory setup: screen + charset base
|
||||
SPRPRI = $d01b ; sprite/background priority
|
||||
SPRMCEN = $d01c ; sprite multicolor enable
|
||||
SPRDBLX = $d01d ; sprite x expand
|
||||
SPRCOL = $d027 ; sprite colors, 8 registers
|
||||
CPUPORT = $01 ; 6510 port: ROM/RAM banking
|
||||
CIA1_PA = $dc00 ; CIA1 port A: keyboard columns / joystick 2
|
||||
CIA1_PB = $dc01 ; CIA1 port B: keyboard rows / joystick 1
|
||||
CIA1_TA = $dc04 ; CIA1 timer A low byte: free-running entropy
|
||||
|
||||
CHARSET = $3800 ; RAM charset: ROM font + the custom tiles
|
||||
SPRPTR = SCREEN + $3f8 ; sprite shape pointers
|
||||
|
||||
; ---- SID registers (single-voice SFX driver) ----
|
||||
SID_V1FL = $d400 ; voice 1 frequency low
|
||||
SID_V1FH = $d401 ; voice 1 frequency high
|
||||
@@ -71,16 +85,24 @@ MAZE_CH = 11 ; cells down
|
||||
NCELLS = MAZE_CW * MAZE_CH
|
||||
NENEMIES = 4
|
||||
|
||||
CH_WALL = $a0 ; inverse space: solid wall block
|
||||
; ---- characters (the custom tiles live in the RAM charset) ----
|
||||
CH_WALL = $e0 ; brick block: spinnable wall piece
|
||||
CH_POST = $e1 ; bolted plate: fixed pivot post
|
||||
CH_EXIT = $e2 ; the portal out (4 animated glyph frames)
|
||||
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
|
||||
CH_BAR = $e3 ; 7 chars: a bar cell 1-7 pixels full
|
||||
|
||||
; ---- the actors are hardware sprites ----
|
||||
SP_RUN = 0 ; player 1, the runner
|
||||
SP_CUR = 1 ; player 2, the corner cursor
|
||||
SP_SHOT = 2 ; the optional bullet
|
||||
SP_EN = 3 ; the enemies ride sprites 3-6
|
||||
|
||||
COL_WALL = MGREY ; spinnable wall pieces
|
||||
COL_POST = DGREY ; fixed pivot posts
|
||||
COL_EXIT = LGREEN ; the exit diamond
|
||||
COL_EXIT = LGREEN ; the exit portal
|
||||
COL_HILITE = YELLOW ; walls the cursor's spin would move
|
||||
STATCOL = BLUE ; background band behind the status row
|
||||
|
||||
; ---- game timing ----
|
||||
REP_HOLD = 10 ; runner: frames before a held dir repeats
|
||||
@@ -90,6 +112,7 @@ 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
|
||||
BUILD_STEPS = 8 ; maze carve animation: generator steps a frame
|
||||
|
||||
; ---- zero page pointers (same slots as rabbitc64) ----
|
||||
txtlo = $f5 ; text pointer for the print routines (2 bytes)
|
||||
@@ -140,3 +163,13 @@ colhi = $fe
|
||||
lda #>.addr
|
||||
sta updvec+1
|
||||
}
|
||||
|
||||
; ---- leave the current screen: fade to black, then run the
|
||||
; init routine of the next one ----
|
||||
!macro fadeto .addr {
|
||||
lda #<.addr
|
||||
sta fadevec
|
||||
lda #>.addr
|
||||
sta fadevec+1
|
||||
jmp fade_start
|
||||
}
|
||||
|
||||
@@ -0,0 +1,481 @@
|
||||
; -----------------------------------------------------------
|
||||
; gfx.asm - the graphics layer:
|
||||
; - the ROM font is copied into RAM and a handful of custom
|
||||
; tiles are stamped over it (brick wall, pivot post, the
|
||||
; animated exit portal, the 1/8-step cooldown bar cells)
|
||||
; - a small sprite engine: every actor lives on the char
|
||||
; grid, its sprite glides toward the cell a few pixels a
|
||||
; frame (the runner bobs, the enemies wave)
|
||||
; - fade to black: the transition between two screens
|
||||
; -----------------------------------------------------------
|
||||
|
||||
; ---- one-time setup: font to RAM, custom tiles, VIC ----
|
||||
gfx_init:
|
||||
lda #$33 ; char ROM in at $d000 (I/O out briefly)
|
||||
sta CPUPORT
|
||||
lda #$d0
|
||||
sta txthi
|
||||
lda #>CHARSET
|
||||
sta scrhi
|
||||
lda #0
|
||||
sta txtlo
|
||||
sta scrlo
|
||||
ldx #8 ; 2 KB: the full uppercase set
|
||||
gc_page:
|
||||
ldy #0
|
||||
gc_byte:
|
||||
lda (txtlo),y
|
||||
sta (scrlo),y
|
||||
iny
|
||||
bne gc_byte
|
||||
inc txthi
|
||||
inc scrhi
|
||||
dex
|
||||
bne gc_page
|
||||
lda #$37 ; I/O back in
|
||||
sta CPUPORT
|
||||
; the brick wall + the pivot post (two consecutive codes)
|
||||
ldx #15
|
||||
gc_tiles:
|
||||
lda tile_gfx,x
|
||||
sta CHARSET+CH_WALL*8,x
|
||||
dex
|
||||
bpl gc_tiles
|
||||
; the portal starts on frame 0
|
||||
ldx #7
|
||||
gc_portal:
|
||||
lda portal_gfx,x
|
||||
sta CHARSET+CH_EXIT*8,x
|
||||
dex
|
||||
bpl gc_portal
|
||||
; the seven bar cells: 1-7 pixels filled from the left
|
||||
ldx #0
|
||||
ldy #0
|
||||
gc_bar:
|
||||
lda barmask,x
|
||||
sta rtmp
|
||||
lda #8
|
||||
sta rtmp2
|
||||
gc_bar8:
|
||||
lda rtmp
|
||||
sta CHARSET+CH_BAR*8,y
|
||||
iny
|
||||
dec rtmp2
|
||||
bne gc_bar8
|
||||
inx
|
||||
cpx #7
|
||||
bne gc_bar
|
||||
; VIC: screen at $0400, charset at $3800
|
||||
lda #$1e
|
||||
sta VMCSB
|
||||
; sprites: hires, unexpanded, in front of the chars
|
||||
lda #0
|
||||
sta SPRDBLY
|
||||
sta SPRDBLX
|
||||
sta SPRMCEN
|
||||
sta SPRPRI
|
||||
sta SPRMSB
|
||||
rts
|
||||
|
||||
; ---- cycle the portal glyph: 4 frames, one every 8 frames;
|
||||
; rewriting the definition animates every portal on screen ----
|
||||
upd_portal:
|
||||
lda framectr
|
||||
and #7
|
||||
bne up_done
|
||||
lda framectr
|
||||
and #$18 ; (frame index) * 8 = data offset
|
||||
tay
|
||||
ldx #0
|
||||
up_copy:
|
||||
lda portal_gfx,y
|
||||
sta CHARSET+CH_EXIT*8,x
|
||||
iny
|
||||
inx
|
||||
cpx #8
|
||||
bne up_copy
|
||||
up_done:
|
||||
rts
|
||||
|
||||
; ============================================================
|
||||
; sprite engine
|
||||
; ============================================================
|
||||
|
||||
; grid cell (tgc, tgr) -> pixel target tgxl/tgxh, tgy
|
||||
set_target:
|
||||
lda #0
|
||||
sta tgxh
|
||||
lda tgc
|
||||
asl
|
||||
rol tgxh
|
||||
asl
|
||||
rol tgxh
|
||||
asl
|
||||
rol tgxh
|
||||
clc
|
||||
adc #24 ; first visible pixel column
|
||||
sta tgxl
|
||||
bcc st_y
|
||||
inc tgxh
|
||||
st_y:
|
||||
lda tgr
|
||||
asl
|
||||
asl
|
||||
asl
|
||||
clc
|
||||
adc #50 ; first visible raster line
|
||||
sta tgy
|
||||
rts
|
||||
|
||||
; sprite X snaps straight onto the target
|
||||
spr_jump:
|
||||
lda tgxl
|
||||
sta sprxl,x
|
||||
lda tgxh
|
||||
sta sprxh,x
|
||||
lda tgy
|
||||
sta spry,x
|
||||
rts
|
||||
|
||||
; sprite X slides gspd pixels per axis toward the target; the
|
||||
; actors re-target every frame, so the distance always fits in
|
||||
; a signed byte and a step never overshoots
|
||||
spr_glide:
|
||||
lda tgxl
|
||||
sec
|
||||
sbc sprxl,x
|
||||
sta dtmp
|
||||
lda tgxh
|
||||
sbc sprxh,x ; the high byte only carries the sign
|
||||
lda dtmp
|
||||
beq sg_y
|
||||
bmi sg_left
|
||||
cmp gspd ; rightward: step = min(distance, speed)
|
||||
bcc sg_rgo
|
||||
lda gspd
|
||||
sg_rgo:
|
||||
clc
|
||||
adc sprxl,x
|
||||
sta sprxl,x
|
||||
bcc sg_y
|
||||
inc sprxh,x
|
||||
jmp sg_y
|
||||
sg_left:
|
||||
eor #$ff ; leftward: the same on the distance
|
||||
clc
|
||||
adc #1
|
||||
cmp gspd
|
||||
bcc sg_lgo
|
||||
lda gspd
|
||||
sg_lgo:
|
||||
sta dtmp
|
||||
lda sprxl,x
|
||||
sec
|
||||
sbc dtmp
|
||||
sta sprxl,x
|
||||
bcs sg_y
|
||||
dec sprxh,x
|
||||
sg_y:
|
||||
lda tgy
|
||||
sec
|
||||
sbc spry,x
|
||||
beq sg_done
|
||||
bmi sg_up
|
||||
cmp gspd
|
||||
bcc sg_dgo
|
||||
lda gspd
|
||||
sg_dgo:
|
||||
clc
|
||||
adc spry,x
|
||||
sta spry,x
|
||||
rts
|
||||
sg_up:
|
||||
eor #$ff
|
||||
clc
|
||||
adc #1
|
||||
cmp gspd
|
||||
bcc sg_ugo
|
||||
lda gspd
|
||||
sg_ugo:
|
||||
sta dtmp
|
||||
lda spry,x
|
||||
sec
|
||||
sbc dtmp
|
||||
sta spry,x
|
||||
sg_done:
|
||||
rts
|
||||
|
||||
; push all eight sprite positions + the x msb bits to the VIC
|
||||
spr_commit:
|
||||
lda #0
|
||||
sta dtmp
|
||||
ldx #7
|
||||
sc_loop:
|
||||
lda sprxh,x
|
||||
beq sc_low
|
||||
lda dtmp
|
||||
ora sprbit,x
|
||||
sta dtmp
|
||||
sc_low:
|
||||
txa
|
||||
asl
|
||||
tay
|
||||
lda sprxl,x
|
||||
sta SPRX0,y
|
||||
lda spry,x
|
||||
sta SPRY0,y
|
||||
dex
|
||||
bpl sc_loop
|
||||
lda dtmp
|
||||
sta SPRMSB
|
||||
rts
|
||||
|
||||
sprbit: !byte 1, 2, 4, 8, 16, 32, 64, 128
|
||||
|
||||
; ============================================================
|
||||
; fade to black - six passes walk every color RAM cell (and
|
||||
; the sprite colors) down the luminance chains, half a screen
|
||||
; per frame; then control jumps to the init routine the
|
||||
; +fadeto macro left in fadevec
|
||||
; ============================================================
|
||||
fade_start:
|
||||
lda #$ff
|
||||
sta statbg ; no status band while fading
|
||||
lda #0
|
||||
sta bflash
|
||||
sta borbase
|
||||
sta fadecnt
|
||||
sta fadehalf
|
||||
+setupd fade_update
|
||||
rts
|
||||
|
||||
fade_update:
|
||||
lda fadehalf ; half the color RAM per frame
|
||||
eor #1
|
||||
sta fadehalf
|
||||
bne fu_hi
|
||||
ldx #0
|
||||
fu_lo:
|
||||
lda COLRAM,x
|
||||
and #15
|
||||
tay
|
||||
lda fadetbl,y
|
||||
sta COLRAM,x
|
||||
lda COLRAM+$100,x
|
||||
and #15
|
||||
tay
|
||||
lda fadetbl,y
|
||||
sta COLRAM+$100,x
|
||||
inx
|
||||
bne fu_lo
|
||||
rts
|
||||
fu_hi:
|
||||
ldx #0
|
||||
fu_hi2:
|
||||
lda COLRAM+$200,x
|
||||
and #15
|
||||
tay
|
||||
lda fadetbl,y
|
||||
sta COLRAM+$200,x
|
||||
lda COLRAM+$2e8,x
|
||||
and #15
|
||||
tay
|
||||
lda fadetbl,y
|
||||
sta COLRAM+$2e8,x
|
||||
inx
|
||||
bne fu_hi2
|
||||
ldx #7 ; the sprites sink with the screen
|
||||
fu_spr:
|
||||
lda SPRCOL,x
|
||||
and #15
|
||||
tay
|
||||
lda fadetbl,y
|
||||
sta SPRCOL,x
|
||||
dex
|
||||
bpl fu_spr
|
||||
inc fadecnt
|
||||
lda fadecnt
|
||||
cmp #6 ; the longest chain is black after 5
|
||||
bne fu_stay
|
||||
lda #0
|
||||
sta SPR_EN
|
||||
jmp (fadevec) ; its rts returns to the main loop
|
||||
fu_stay:
|
||||
rts
|
||||
|
||||
fadetbl: ; each color, one step darker
|
||||
!byte $00, $0f, $09, $0c, $0b, $0b, $00, $08
|
||||
!byte $02, $00, $02, $00, $0b, $05, $06, $0c
|
||||
|
||||
; ---- the custom tiles ----
|
||||
tile_gfx: ; CH_WALL: bricks with dark mortar
|
||||
!byte %11111111
|
||||
!byte %11110111
|
||||
!byte %11110111
|
||||
!byte %00000000
|
||||
!byte %11111111
|
||||
!byte %01111111
|
||||
!byte %01111111
|
||||
!byte %00000000
|
||||
; CH_POST: a bolted plate
|
||||
!byte %11111111
|
||||
!byte %10000001
|
||||
!byte %10111101
|
||||
!byte %10100101
|
||||
!byte %10100101
|
||||
!byte %10111101
|
||||
!byte %10000001
|
||||
!byte %11111111
|
||||
|
||||
portal_gfx: ; CH_EXIT frame 0: closed
|
||||
!byte %00000000
|
||||
!byte %00011000
|
||||
!byte %00111100
|
||||
!byte %01100110
|
||||
!byte %01100110
|
||||
!byte %00111100
|
||||
!byte %00011000
|
||||
!byte %00000000
|
||||
; frame 1: opening
|
||||
!byte %00011000
|
||||
!byte %00111100
|
||||
!byte %01100110
|
||||
!byte %11000011
|
||||
!byte %11000011
|
||||
!byte %01100110
|
||||
!byte %00111100
|
||||
!byte %00011000
|
||||
; frame 2: wide open, sparkling
|
||||
!byte %00111100
|
||||
!byte %01100110
|
||||
!byte %11011011
|
||||
!byte %10111101
|
||||
!byte %10111101
|
||||
!byte %11011011
|
||||
!byte %01100110
|
||||
!byte %00111100
|
||||
; frame 3: closing again
|
||||
!byte %00011000
|
||||
!byte %00111100
|
||||
!byte %01100110
|
||||
!byte %11000011
|
||||
!byte %11000011
|
||||
!byte %01100110
|
||||
!byte %00111100
|
||||
!byte %00011000
|
||||
|
||||
barmask: ; bar cell fills, 1-7 pixels
|
||||
!byte $80, $c0, $e0, $f0, $f8, $fc, $fe
|
||||
|
||||
; ---- graphics layer variables ----
|
||||
sprxl: !fill 8, 0 ; sprite pixel positions (x low/high, y)
|
||||
sprxh: !fill 8, 0
|
||||
spry: !fill 8, 0
|
||||
tgc: !byte 0 ; set_target input: grid column / row
|
||||
tgr: !byte 0
|
||||
tgxl: !byte 0 ; set_target output: pixel target
|
||||
tgxh: !byte 0
|
||||
tgy: !byte 0
|
||||
gspd: !byte 0 ; spr_glide: pixels per frame
|
||||
dtmp: !byte 0 ; scratch
|
||||
statbg: !byte $ff ; status band color, $ff = no band
|
||||
bflash: !byte 0 ; border flash: frames left + color
|
||||
bcolor: !byte 0
|
||||
borbase: !byte 0 ; steady border color of the screen
|
||||
fadevec: !byte 0, 0 ; where fade_update jumps when done
|
||||
fadecnt: !byte 0 ; fade passes completed
|
||||
fadehalf: !byte 0 ; which color RAM half is next
|
||||
|
||||
!if (fadevec & 255) = 255 { !error "fadevec must not straddle a page" }
|
||||
|
||||
; ---- sprite shapes: 8x8 art in the top-left of each block ----
|
||||
!align 63, 0
|
||||
spr_run0: ; the runner: a bright-eyed ball...
|
||||
!byte %00111100, 0, 0
|
||||
!byte %01111110, 0, 0
|
||||
!byte %11011011, 0, 0
|
||||
!byte %11111111, 0, 0
|
||||
!byte %11111111, 0, 0
|
||||
!byte %11111111, 0, 0
|
||||
!byte %01111110, 0, 0
|
||||
!byte %00111100, 0, 0
|
||||
!fill 40, 0
|
||||
spr_run1: ; ...that bobs as it goes
|
||||
!byte %00000000, 0, 0
|
||||
!byte %00111100, 0, 0
|
||||
!byte %01111110, 0, 0
|
||||
!byte %11011011, 0, 0
|
||||
!byte %11111111, 0, 0
|
||||
!byte %11111111, 0, 0
|
||||
!byte %01111110, 0, 0
|
||||
!byte %00111100, 0, 0
|
||||
!fill 40, 0
|
||||
spr_shot0: ; the bullet
|
||||
!byte %00000000, 0, 0
|
||||
!byte %00000000, 0, 0
|
||||
!byte %00011000, 0, 0
|
||||
!byte %00111100, 0, 0
|
||||
!byte %00111100, 0, 0
|
||||
!byte %00011000, 0, 0
|
||||
!byte %00000000, 0, 0
|
||||
!byte %00000000, 0, 0
|
||||
!fill 40, 0
|
||||
spr_cur0: ; the corner cursor: four brackets
|
||||
!byte %11100111, 0, 0
|
||||
!byte %10000001, 0, 0
|
||||
!byte %10000001, 0, 0
|
||||
!byte %00000000, 0, 0
|
||||
!byte %00000000, 0, 0
|
||||
!byte %10000001, 0, 0
|
||||
!byte %10000001, 0, 0
|
||||
!byte %11100111, 0, 0
|
||||
!fill 40, 0
|
||||
spr_ena0: ; enemies 0-1: a ghost, skirt waving
|
||||
!byte %00111100, 0, 0
|
||||
!byte %01111110, 0, 0
|
||||
!byte %11011011, 0, 0
|
||||
!byte %11011011, 0, 0
|
||||
!byte %11111111, 0, 0
|
||||
!byte %11111111, 0, 0
|
||||
!byte %11111111, 0, 0
|
||||
!byte %10110101, 0, 0
|
||||
!fill 40, 0
|
||||
spr_ena1:
|
||||
!byte %00111100, 0, 0
|
||||
!byte %01111110, 0, 0
|
||||
!byte %11011011, 0, 0
|
||||
!byte %11011011, 0, 0
|
||||
!byte %11111111, 0, 0
|
||||
!byte %11111111, 0, 0
|
||||
!byte %11111111, 0, 0
|
||||
!byte %01101101, 0, 0
|
||||
!fill 40, 0
|
||||
spr_enb0: ; enemies 2-3: a crawler, legs pumping
|
||||
!byte %00000000, 0, 0
|
||||
!byte %10111101, 0, 0
|
||||
!byte %01111110, 0, 0
|
||||
!byte %11011011, 0, 0
|
||||
!byte %01111110, 0, 0
|
||||
!byte %10111101, 0, 0
|
||||
!byte %00000000, 0, 0
|
||||
!byte %00000000, 0, 0
|
||||
!fill 40, 0
|
||||
spr_enb1:
|
||||
!byte %00000000, 0, 0
|
||||
!byte %00111100, 0, 0
|
||||
!byte %01111110, 0, 0
|
||||
!byte %11011011, 0, 0
|
||||
!byte %01111110, 0, 0
|
||||
!byte %00111100, 0, 0
|
||||
!byte %00000000, 0, 0
|
||||
!byte %00000000, 0, 0
|
||||
!fill 40, 0
|
||||
|
||||
SPR_RUN = spr_run0 DIV 64
|
||||
SPR_SHOT = spr_shot0 DIV 64
|
||||
SPR_CUR = spr_cur0 DIV 64
|
||||
SPR_ENA = spr_ena0 DIV 64
|
||||
SPR_ENB = spr_enb0 DIV 64
|
||||
|
||||
!if spr_run0 < $2000 { !error "sprite data slid under $2000: the VIC sees the char ROM shadow there" }
|
||||
!if * > CHARSET { !error "the program ran into the charset at $3800" }
|
||||
@@ -78,11 +78,11 @@ iw_skip:
|
||||
; fire skips, otherwise wait out the timer
|
||||
jsr start_edge
|
||||
beq iw_tick
|
||||
jmp menu_init
|
||||
+fadeto menu_init
|
||||
iw_tick:
|
||||
dec introt
|
||||
bne iw_done
|
||||
jmp menu_init
|
||||
+fadeto menu_init
|
||||
iw_done:
|
||||
rts
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
; -----------------------------------------------------------
|
||||
; 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
|
||||
; the green exit portal while dodging the roaming colored
|
||||
; enemies; player 2 rides the wall corners with a cursor
|
||||
; and fire spins the four wall pieces around it by 90
|
||||
; degrees, reshaping the maze under the runner's feet
|
||||
@@ -9,7 +9,7 @@
|
||||
; Files:
|
||||
; defs.asm - constants, zero page, macros
|
||||
; intro.asm - TTG boot logo (ported from rabbitc64)
|
||||
; menu.asm - main menu: play / options / rules / ...
|
||||
; menu.asm - main menu over a dark maze backdrop
|
||||
; options.asm - optional extras: runner gun, spin cooldown
|
||||
; rules.asm - how to play
|
||||
; controls.asm- joystick + keyboard mappings
|
||||
@@ -19,6 +19,7 @@
|
||||
; over.asm - game over screen with retry
|
||||
; common.asm - shared routines, input, RNG, texts
|
||||
; sound.asm - single-voice SFX driver
|
||||
; gfx.asm - RAM charset, sprite engine, fades
|
||||
;
|
||||
; Build: acme -f cbm -o labyrintwo.prg main.asm
|
||||
; -----------------------------------------------------------
|
||||
@@ -44,9 +45,10 @@ start:
|
||||
sta BORDER
|
||||
sta BG
|
||||
lda #0
|
||||
sta SPR_EN ; character-only game: sprites stay off
|
||||
sta SPR_EN ; the actors arrive with the game screen
|
||||
sta framectr
|
||||
sta fheld
|
||||
jsr gfx_init ; RAM charset + VIC + sprite registers
|
||||
jsr sfx_init
|
||||
|
||||
!ifdef AUTOPLAY { ; test builds boot straight into one state
|
||||
@@ -81,13 +83,46 @@ start:
|
||||
|
||||
; ============================================================
|
||||
; main loop - one state update per PAL frame, synced to the
|
||||
; raster beam in the lower border
|
||||
; raster beam in the lower border; the loop also paints the
|
||||
; border (event flashes decay back to the screen's base
|
||||
; color) and, when a screen asks for one, lays a background
|
||||
; band behind the status row with two more raster waits
|
||||
; ============================================================
|
||||
main:
|
||||
jsr wait_frame
|
||||
jsr wait_frame ; raster line RAS_SYNC, once a frame
|
||||
lda bflash ; border: flash, else the base color
|
||||
beq mb_base
|
||||
dec bflash
|
||||
lda bcolor
|
||||
jmp mb_border
|
||||
mb_base:
|
||||
lda borbase
|
||||
mb_border:
|
||||
sta BORDER
|
||||
inc framectr
|
||||
jsr rand8 ; stir the RNG once per frame
|
||||
jsr sfx_update ; advance the sound effect
|
||||
lda statbg ; $ff = no band: update right away
|
||||
bmi mb_update
|
||||
mb_w1:
|
||||
bit SCRCTL ; the beam reaches line 256...
|
||||
bpl mb_w1
|
||||
mb_w2:
|
||||
bit SCRCTL ; ...and wraps to line 0
|
||||
bmi mb_w2
|
||||
mb_w3:
|
||||
lda RASTER
|
||||
cmp #49 ; still in the border above the window
|
||||
bcc mb_w3
|
||||
lda statbg
|
||||
sta BG
|
||||
mb_w4:
|
||||
lda RASTER
|
||||
cmp #59 ; the switch back hides behind row 1's
|
||||
bcc mb_w4 ; wall tops (their top line is solid)
|
||||
lda #BLACK
|
||||
sta BG
|
||||
mb_update:
|
||||
jsr call_update
|
||||
jmp main
|
||||
|
||||
@@ -120,3 +155,4 @@ wf_hit:
|
||||
!src "over.asm"
|
||||
!src "common.asm"
|
||||
!src "sound.asm"
|
||||
!src "gfx.asm"
|
||||
|
||||
@@ -11,6 +11,33 @@ MENU_ITEMS = 5
|
||||
menu_init:
|
||||
jsr clear_screen
|
||||
|
||||
; a dark maze weaves behind the whole card
|
||||
lda #DGREY
|
||||
sta latwcol
|
||||
sta latpcol
|
||||
jsr draw_lattice
|
||||
jsr gen_init
|
||||
jsr gen_maze_full
|
||||
|
||||
; a clean panel for the menu itself (rows 9-22, cols 4-35)
|
||||
ldx #9
|
||||
mi_panel:
|
||||
stx ptmp
|
||||
jsr row_ptr
|
||||
ldy #35
|
||||
mi_pcol:
|
||||
lda #$20
|
||||
sta (scrlo),y
|
||||
lda #BLACK
|
||||
sta (collo),y
|
||||
dey
|
||||
cpy #3
|
||||
bne mi_pcol
|
||||
ldx ptmp
|
||||
inx
|
||||
cpx #23
|
||||
bne mi_panel
|
||||
|
||||
+prbig 2, 0, YELLOW, txt_t1, 7
|
||||
+prbig 2, 28, CYAN, txt_t2, 3
|
||||
+prtext 9, 13, LGREY, txt_ttgname, 14
|
||||
@@ -162,15 +189,15 @@ mu_start:
|
||||
beq mg_rules
|
||||
cmp #3
|
||||
beq mg_controls
|
||||
jmp credits_init ; each init's rts returns to the main loop
|
||||
+fadeto credits_init ; every screen change fades to black
|
||||
mg_play:
|
||||
jmp play_init
|
||||
+fadeto play_init
|
||||
mg_options:
|
||||
jmp options_init
|
||||
+fadeto options_init
|
||||
mg_rules:
|
||||
jmp rules_init
|
||||
+fadeto rules_init
|
||||
mg_controls:
|
||||
jmp controls_init
|
||||
+fadeto controls_init
|
||||
mu_done:
|
||||
rts
|
||||
|
||||
|
||||
+1
-1
@@ -122,7 +122,7 @@ ou_done:
|
||||
ou_back:
|
||||
lda #SFX_SELECT
|
||||
jsr sfx_play
|
||||
jmp menu_init
|
||||
+fadeto menu_init
|
||||
|
||||
; ---- draw option line X, yellow when it is the picked one ----
|
||||
draw_oitem:
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
lose_init:
|
||||
jsr clear_screen
|
||||
|
||||
lda #RED ; the border mourns with the letters
|
||||
sta borbase
|
||||
|
||||
+prbig 3, 2, RED, txt_gameover, 9
|
||||
|
||||
+prtext 11, 10, WHITE, txt_caught, txt_caughte-txt_caught
|
||||
@@ -28,7 +31,7 @@ lu_input:
|
||||
; fire or space: straight back in with a fresh maze
|
||||
jsr start_edge
|
||||
beq lu_nofire
|
||||
jmp play_init
|
||||
+fadeto play_init
|
||||
lu_nofire:
|
||||
; the m key: keyboard column 4, row bit 4 (start_edge has
|
||||
; already returned zero here, so joystick fire is not
|
||||
@@ -40,7 +43,7 @@ lu_nofire:
|
||||
bne lu_done
|
||||
lda #$ff
|
||||
sta CIA1_PA
|
||||
jmp menu_init
|
||||
+fadeto menu_init
|
||||
lu_done:
|
||||
lda #$ff
|
||||
sta CIA1_PA
|
||||
|
||||
@@ -33,7 +33,7 @@ ru_hide:
|
||||
ru_input:
|
||||
jsr start_edge
|
||||
beq ru_stay
|
||||
jmp menu_init
|
||||
+fadeto menu_init
|
||||
ru_stay:
|
||||
rts
|
||||
|
||||
|
||||
@@ -17,6 +17,15 @@ win_init:
|
||||
rts
|
||||
|
||||
win_update:
|
||||
; the border celebrates along on the same gold ramp
|
||||
lda framectr
|
||||
lsr
|
||||
lsr
|
||||
and #15
|
||||
tax
|
||||
lda washtbl,x
|
||||
sta borbase
|
||||
|
||||
; the gold wash rolls down the big letters (rows 3-7)
|
||||
inc washphase
|
||||
lda #0
|
||||
@@ -62,7 +71,7 @@ wu_hide:
|
||||
wu_input:
|
||||
jsr start_edge
|
||||
beq wu_stay
|
||||
jmp menu_init ; a win leads back to the main screen
|
||||
+fadeto menu_init ; a win leads back to the main screen
|
||||
wu_stay:
|
||||
rts
|
||||
|
||||
|
||||
Reference in New Issue
Block a user