multiplayer support
This commit is contained in:
@@ -10,12 +10,18 @@ that passes in any other lane is a **point**. Three misses end the round.
|
|||||||
The spawn rate and the rabbits' speed ramp up with your score, just like
|
The spawn rate and the rabbits' speed ramp up with your score, just like
|
||||||
in the original.
|
in the original.
|
||||||
|
|
||||||
|
In **multiplayer** the rabbits still spawn on their own, but player 2
|
||||||
|
steers the closest one left and right, trying to run the scooter down.
|
||||||
|
|
||||||
## Controls
|
## Controls
|
||||||
|
|
||||||
| Input | Action |
|
| Input | Action |
|
||||||
|-------|--------|
|
|-------|--------|
|
||||||
| Joystick port 2 left/right, or `A` / `D` | change lane (auto-repeats while held) |
|
| Menu: joystick up/down, or the `S` / `M` keys | pick single player / multiplayer |
|
||||||
| Fire (or `SPACE`) | start / retry |
|
| Menu: fire (or `SPACE`); the `1` / `2` keys pick and start at once | start the picked mode |
|
||||||
|
| P1: joystick port 2 left/right, or `A` / `D` | move the scooter (auto-repeats while held) |
|
||||||
|
| P2: joystick port 1 left/right, or `J` / `L` | steer the closest rabbit (multiplayer) |
|
||||||
|
| Fire (or `SPACE`) | start; on the game over screen: back to the menu |
|
||||||
|
|
||||||
## How it works
|
## How it works
|
||||||
|
|
||||||
|
|||||||
+48
-5
@@ -206,11 +206,49 @@ rj_noright:
|
|||||||
lda joyb
|
lda joyb
|
||||||
rts
|
rts
|
||||||
|
|
||||||
; fire or space held? returns A != 0 when pressed
|
; read joystick port 1 merged with the j/l keys (player 2),
|
||||||
|
; return active-high bits in A and joyb2
|
||||||
|
read_joy2:
|
||||||
|
lda #$ff ; no column selected: port B = joystick 1
|
||||||
|
sta CIA1_PA
|
||||||
|
lda CIA1_PB
|
||||||
|
eor #$ff
|
||||||
|
and #$1f
|
||||||
|
sta joyb2
|
||||||
|
and #$0f ; a held direction grounds the same port B
|
||||||
|
bne rj2_done ; lines the key rows use: skip the scan
|
||||||
|
lda #$ef ; 'j' = left: keyboard column 4, row bit 2
|
||||||
|
sta CIA1_PA
|
||||||
|
lda CIA1_PB
|
||||||
|
and #$04
|
||||||
|
bne rj2_noleft
|
||||||
|
lda joyb2
|
||||||
|
ora #JOY_LEFT
|
||||||
|
sta joyb2
|
||||||
|
rj2_noleft:
|
||||||
|
lda #$df ; 'l' = right: keyboard column 5, row bit 2
|
||||||
|
sta CIA1_PA
|
||||||
|
lda CIA1_PB
|
||||||
|
and #$04
|
||||||
|
bne rj2_done
|
||||||
|
lda joyb2
|
||||||
|
ora #JOY_RIGHT
|
||||||
|
sta joyb2
|
||||||
|
rj2_done:
|
||||||
|
lda joyb2
|
||||||
|
rts
|
||||||
|
|
||||||
|
; fire on either stick or space held? returns A != 0 when pressed
|
||||||
start_pressed:
|
start_pressed:
|
||||||
jsr read_joy
|
jsr read_joy
|
||||||
and #JOY_FIRE
|
and #JOY_FIRE
|
||||||
bne sp_done
|
bne sp_done
|
||||||
|
lda #$ff ; deselect the columns: port B = joystick 1
|
||||||
|
sta CIA1_PA
|
||||||
|
lda CIA1_PB
|
||||||
|
eor #$ff
|
||||||
|
and #JOY_FIRE
|
||||||
|
bne sp_done
|
||||||
lda #$7f ; space: keyboard column 7, row bit 4
|
lda #$7f ; space: keyboard column 7, row bit 4
|
||||||
sta CIA1_PA
|
sta CIA1_PA
|
||||||
lda CIA1_PB
|
lda CIA1_PB
|
||||||
@@ -546,12 +584,14 @@ txt_score: !scr "score"
|
|||||||
txt_miss: !scr "miss"
|
txt_miss: !scr "miss"
|
||||||
txt_rabbit: !scr "rabbit"
|
txt_rabbit: !scr "rabbit"
|
||||||
txt_scooter: !scr "scooter"
|
txt_scooter: !scr "scooter"
|
||||||
txt_press: !scr "fire = start game"
|
txt_1p: !scr "single player"
|
||||||
txt_info: !scr "joystick 2 or a/d moves"
|
txt_2p: !scr "multiplayer"
|
||||||
|
txt_info: !scr "p1: joystick 2 or a/d"
|
||||||
|
txt_info2: !scr "p2: joystick 1 or j/l"
|
||||||
txt_ttgname: !scr "teletype games"
|
txt_ttgname: !scr "teletype games"
|
||||||
txt_presents:!scr "presents"
|
txt_presents:!scr "presents"
|
||||||
txt_over: !scr "game over"
|
txt_over: !scr "game over"
|
||||||
txt_retry: !scr "fire = retry"
|
txt_return: !scr "fire = return"
|
||||||
txt_blank: !fill 19, $20
|
txt_blank: !fill 19, $20
|
||||||
|
|
||||||
washtbl: ; gold glow ramp (16 entries, cyclic)
|
washtbl: ; gold glow ramp (16 entries, cyclic)
|
||||||
@@ -565,7 +605,10 @@ bg_top: !byte COL_SKY ; background color above / below the
|
|||||||
bg_bot: !byte COL_GRASS ; horizon raster split
|
bg_bot: !byte COL_GRASS ; horizon raster split
|
||||||
seed: !byte $a7 ; rand8 LFSR state
|
seed: !byte $a7 ; rand8 LFSR state
|
||||||
fheld: !byte 0 ; fire/space edge detection state
|
fheld: !byte 0 ; fire/space edge detection state
|
||||||
joyb: !byte 0 ; joystick bits from read_joy (active high)
|
joyb: !byte 0 ; player 1 input bits from read_joy
|
||||||
|
joyb2: !byte 0 ; player 2 input bits from read_joy2
|
||||||
|
mp_mode: !byte 0 ; 0 = single player, 1 = multiplayer
|
||||||
|
k12held: !byte 0 ; menu '1'/'2' key edge detection state
|
||||||
en_sh: !byte 0 ; per-frame sprite register shadows
|
en_sh: !byte 0 ; per-frame sprite register shadows
|
||||||
msb_sh: !byte 0
|
msb_sh: !byte 0
|
||||||
xex_sh: !byte 0
|
xex_sh: !byte 0
|
||||||
|
|||||||
@@ -32,17 +32,17 @@ over_init:
|
|||||||
rts
|
rts
|
||||||
|
|
||||||
over_update:
|
over_update:
|
||||||
; blink the retry prompt
|
; blink the return prompt
|
||||||
lda framectr
|
lda framectr
|
||||||
and #32
|
and #32
|
||||||
bne ou_hide
|
bne ou_hide
|
||||||
+prtext 16, 14, YELLOW, txt_retry, 12
|
+prtext 16, 13, YELLOW, txt_return, 13
|
||||||
jmp ou_start
|
jmp ou_start
|
||||||
ou_hide:
|
ou_hide:
|
||||||
+prtext 16, 14, YELLOW, txt_blank, 12
|
+prtext 16, 13, YELLOW, txt_blank, 13
|
||||||
ou_start:
|
ou_start:
|
||||||
jsr start_edge
|
jsr start_edge
|
||||||
beq ou_done
|
beq ou_done
|
||||||
jmp play_init ; its rts returns to the main loop
|
jmp title_init ; back to the menu, mode can be re-picked
|
||||||
ou_done:
|
ou_done:
|
||||||
rts
|
rts
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ play_init:
|
|||||||
sta spawnt
|
sta spawnt
|
||||||
sta lcnt
|
sta lcnt
|
||||||
sta rcnt
|
sta rcnt
|
||||||
|
sta p2lcnt
|
||||||
|
sta p2rcnt
|
||||||
jsr draw_score
|
jsr draw_score
|
||||||
|
|
||||||
lda #0 ; draw_score leaves a digit code in A
|
lda #0 ; draw_score leaves a digit code in A
|
||||||
@@ -113,6 +115,52 @@ pu_rrel:
|
|||||||
sta rcnt
|
sta rcnt
|
||||||
pu_rend:
|
pu_rend:
|
||||||
|
|
||||||
|
; -- multiplayer: player 2 steers the closest rabbit --
|
||||||
|
lda mp_mode
|
||||||
|
beq pu_nop2
|
||||||
|
jsr read_joy2
|
||||||
|
lda joyb2
|
||||||
|
and #JOY_LEFT
|
||||||
|
beq pu_p2lrel
|
||||||
|
inc p2lcnt
|
||||||
|
lda p2lcnt
|
||||||
|
cmp #1
|
||||||
|
beq pu_p2lmove
|
||||||
|
cmp #REP_HOLD+REP_PERIOD
|
||||||
|
bne pu_p2lend
|
||||||
|
lda #REP_HOLD
|
||||||
|
sta p2lcnt
|
||||||
|
pu_p2lmove:
|
||||||
|
lda #$ff ; one lane to the left
|
||||||
|
sta rtmp2
|
||||||
|
jsr steer_closest
|
||||||
|
jmp pu_p2lend
|
||||||
|
pu_p2lrel:
|
||||||
|
lda #0
|
||||||
|
sta p2lcnt
|
||||||
|
pu_p2lend:
|
||||||
|
lda joyb2
|
||||||
|
and #JOY_RIGHT
|
||||||
|
beq pu_p2rrel
|
||||||
|
inc p2rcnt
|
||||||
|
lda p2rcnt
|
||||||
|
cmp #1
|
||||||
|
beq pu_p2rmove
|
||||||
|
cmp #REP_HOLD+REP_PERIOD
|
||||||
|
bne pu_p2rend
|
||||||
|
lda #REP_HOLD
|
||||||
|
sta p2rcnt
|
||||||
|
pu_p2rmove:
|
||||||
|
lda #1 ; one lane to the right
|
||||||
|
sta rtmp2
|
||||||
|
jsr steer_closest
|
||||||
|
jmp pu_p2rend
|
||||||
|
pu_p2rrel:
|
||||||
|
lda #0
|
||||||
|
sta p2rcnt
|
||||||
|
pu_p2rend:
|
||||||
|
pu_nop2:
|
||||||
|
|
||||||
; -- shadow init: player sprite bit + its x MSB --
|
; -- shadow init: player sprite bit + its x MSB --
|
||||||
ldx player_lane
|
ldx player_lane
|
||||||
lda pxlo,x
|
lda pxlo,x
|
||||||
@@ -197,6 +245,36 @@ pu_rnext:
|
|||||||
pu_done:
|
pu_done:
|
||||||
rts
|
rts
|
||||||
|
|
||||||
|
; ---- shift the closest live rabbit's lane by rtmp2 (+/-1) ----
|
||||||
|
steer_closest:
|
||||||
|
ldx #$ff ; best slot so far
|
||||||
|
lda #0
|
||||||
|
sta rtmp ; best t so far
|
||||||
|
ldy #NRABBITS-1
|
||||||
|
stc_find:
|
||||||
|
lda r_act,y
|
||||||
|
beq stc_next
|
||||||
|
lda r_thi,y
|
||||||
|
cmp rtmp
|
||||||
|
bcc stc_next
|
||||||
|
sta rtmp
|
||||||
|
tya
|
||||||
|
tax
|
||||||
|
stc_next:
|
||||||
|
dey
|
||||||
|
bpl stc_find
|
||||||
|
cpx #$ff
|
||||||
|
beq stc_done ; no rabbit on the road
|
||||||
|
lda r_lane,x
|
||||||
|
clc
|
||||||
|
adc rtmp2
|
||||||
|
bmi stc_done ; already on the leftmost lane
|
||||||
|
cmp #LANES
|
||||||
|
bcs stc_done ; ... or the rightmost one
|
||||||
|
sta r_lane,x
|
||||||
|
stc_done:
|
||||||
|
rts
|
||||||
|
|
||||||
; ---- claim a free rabbit slot and roll its lane + speed ----
|
; ---- claim a free rabbit slot and roll its lane + speed ----
|
||||||
spawn_rabbit:
|
spawn_rabbit:
|
||||||
ldx #NRABBITS-1
|
ldx #NRABBITS-1
|
||||||
@@ -298,6 +376,8 @@ flash: !byte 0 ; frames left of the post-hit blink
|
|||||||
spawnt: !byte 0 ; frames since the last spawn
|
spawnt: !byte 0 ; frames since the last spawn
|
||||||
lcnt: !byte 0 ; held-direction counters for the auto-repeat
|
lcnt: !byte 0 ; held-direction counters for the auto-repeat
|
||||||
rcnt: !byte 0
|
rcnt: !byte 0
|
||||||
|
p2lcnt: !byte 0 ; the same for player 2's steering
|
||||||
|
p2rcnt: !byte 0
|
||||||
|
|
||||||
; ---- rabbit slots (hardware sprites 1-7) ----
|
; ---- rabbit slots (hardware sprites 1-7) ----
|
||||||
r_act: !fill NRABBITS, 0
|
r_act: !fill NRABBITS, 0
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
; -----------------------------------------------------------
|
; -----------------------------------------------------------
|
||||||
; title.asm - full-screen menu card: big RABBIT / SCOOTER
|
; title.asm - full-screen menu card: big RABBIT / SCOOTER
|
||||||
; logo flanked by two hopping rabbits, the scooter waiting at
|
; logo flanked by two hopping rabbits, single/multiplayer
|
||||||
; the bottom, blinking "fire = start game"
|
; picker (joystick up/down + fire, or the 1 / 2 keys)
|
||||||
; -----------------------------------------------------------
|
; -----------------------------------------------------------
|
||||||
|
|
||||||
title_init:
|
title_init:
|
||||||
@@ -12,7 +12,8 @@ title_init:
|
|||||||
|
|
||||||
+prbig 2, 8, RED, txt_rabbit, 6
|
+prbig 2, 8, RED, txt_rabbit, 6
|
||||||
+prbig 8, 6, WHITE, txt_scooter, 7
|
+prbig 8, 6, WHITE, txt_scooter, 7
|
||||||
+prtext 18, 8, WHITE, txt_info, 23
|
+prtext 18, 9, LGREY, txt_info, 21
|
||||||
|
+prtext 19, 9, LGREY, txt_info2, 21
|
||||||
|
|
||||||
; decoration: white rabbits flank the logo (sprites 1-2,
|
; decoration: white rabbits flank the logo (sprites 1-2,
|
||||||
; double-sized), the red scooter waits at the bottom
|
; double-sized), the red scooter waits at the bottom
|
||||||
@@ -65,17 +66,99 @@ title_update:
|
|||||||
adc #SPRP_BIG
|
adc #SPRP_BIG
|
||||||
sta SPRPTR+2
|
sta SPRPTR+2
|
||||||
|
|
||||||
; blink the start line
|
; joystick up/down picks the mode
|
||||||
|
jsr read_joy
|
||||||
|
lda joyb
|
||||||
|
and #1 ; up
|
||||||
|
beq tu_noup
|
||||||
|
lda #0
|
||||||
|
sta mp_mode
|
||||||
|
tu_noup:
|
||||||
|
lda joyb
|
||||||
|
and #2 ; down
|
||||||
|
beq tu_nodown
|
||||||
|
lda #1
|
||||||
|
sta mp_mode
|
||||||
|
tu_nodown:
|
||||||
|
|
||||||
|
; the 's' / 'm' keys pick the mode (fire still starts)
|
||||||
|
lda #$fd ; 's': keyboard column 1, row bit 5
|
||||||
|
sta CIA1_PA
|
||||||
|
lda CIA1_PB
|
||||||
|
and #$20
|
||||||
|
bne tu_nos
|
||||||
|
lda #0
|
||||||
|
sta mp_mode
|
||||||
|
tu_nos:
|
||||||
|
lda #$ef ; 'm': keyboard column 4, row bit 4
|
||||||
|
sta CIA1_PA
|
||||||
|
lda CIA1_PB
|
||||||
|
and #$10
|
||||||
|
bne tu_nom
|
||||||
|
lda #1
|
||||||
|
sta mp_mode
|
||||||
|
tu_nom:
|
||||||
|
|
||||||
|
; the 1 / 2 keys pick and start right away (edge detected)
|
||||||
|
lda #$7f ; keyboard column 7: '1' = bit 0, '2' = bit 3
|
||||||
|
sta CIA1_PA
|
||||||
|
lda CIA1_PB
|
||||||
|
and #$09
|
||||||
|
cmp #$09
|
||||||
|
beq tu_keyup ; neither key held
|
||||||
|
ldx k12held
|
||||||
|
bne tu_menu ; still held from an earlier frame
|
||||||
|
inx
|
||||||
|
stx k12held
|
||||||
|
and #$01
|
||||||
|
bne tu_key2
|
||||||
|
lda #0
|
||||||
|
sta mp_mode
|
||||||
|
jmp title_go
|
||||||
|
tu_key2:
|
||||||
|
lda #1
|
||||||
|
sta mp_mode
|
||||||
|
jmp title_go
|
||||||
|
tu_keyup:
|
||||||
|
lda #0
|
||||||
|
sta k12held
|
||||||
|
tu_menu:
|
||||||
|
|
||||||
|
; the two options: the picked line is yellow
|
||||||
|
lda mp_mode
|
||||||
|
bne tm_multi
|
||||||
|
+prtext 14, 14, YELLOW, txt_1p, 13
|
||||||
|
+prtext 16, 14, WHITE, txt_2p, 11
|
||||||
|
jmp tm_cursor
|
||||||
|
tm_multi:
|
||||||
|
+prtext 14, 14, WHITE, txt_1p, 13
|
||||||
|
+prtext 16, 14, YELLOW, txt_2p, 11
|
||||||
|
tm_cursor:
|
||||||
|
; blinking '>' cursor in front of the picked line
|
||||||
|
lda #$20
|
||||||
|
sta SCREEN+14*40+12
|
||||||
|
sta SCREEN+16*40+12
|
||||||
lda framectr
|
lda framectr
|
||||||
and #32
|
and #16
|
||||||
bne tu_hide
|
bne tu_start
|
||||||
+prtext 15, 11, YELLOW, txt_press, 17
|
lda mp_mode
|
||||||
|
bne tm_cur2
|
||||||
|
lda #62 ; '>'
|
||||||
|
sta SCREEN+14*40+12
|
||||||
|
lda #YELLOW
|
||||||
|
sta COLRAM+14*40+12
|
||||||
jmp tu_start
|
jmp tu_start
|
||||||
tu_hide:
|
tm_cur2:
|
||||||
+prtext 15, 11, YELLOW, txt_blank, 17
|
lda #62
|
||||||
|
sta SCREEN+16*40+12
|
||||||
|
lda #YELLOW
|
||||||
|
sta COLRAM+16*40+12
|
||||||
|
|
||||||
tu_start:
|
tu_start:
|
||||||
|
; fire or space starts the picked mode
|
||||||
jsr start_edge
|
jsr start_edge
|
||||||
beq tu_done
|
beq tu_done
|
||||||
|
title_go:
|
||||||
jmp play_init ; its rts returns to the main loop
|
jmp play_init ; its rts returns to the main loop
|
||||||
tu_done:
|
tu_done:
|
||||||
rts
|
rts
|
||||||
|
|||||||
Reference in New Issue
Block a user