fujirun/actors.s

374 lines
9.5 KiB
ArmAsm

level_enemies .byte 55, 2, 5, 6, 7, 8 ;# level starts counting from 1, so dummy zeroth level info
level_speed_l .byte 255, 200, 210, 220, 230, 240 ;# increment of fractional pixel per game frame
level_speed_h .byte 2, 2, 2, 2, 2, 2
;level_speed_h .byte 0, 0, 0, 0, 0, 0
player_score_row .byte 2, 7, 12, 17
player_lives_row .byte 3, 8, 13, 18
player_score_l .byte 0, 0, 0, 0
player_score_m .byte 0, 0, 0, 0
player_score_h .byte 0, 0, 0, 0
;# sprites all use the same table. In the sample configuration, sprites 0 - 3
;# are players, 4 and above are enemies. One is an orbiter enemy, the rest use
;# amidar movement.
MAX_PLAYERS = 4
MAX_AMIDARS = VPATH_NUM + 1 ; # one enemy per vpath + one orbiter
;MAX_ACTORS = MAX_PLAYERS + MAX_AMIDARS
MAX_ACTORS = 16
FIRST_PLAYER = 0
FIRST_AMIDAR = MAX_PLAYERS
LAST_PLAYER = FIRST_AMIDAR - 1
LAST_AMIDAR = LAST_PLAYER + MAX_AMIDARS
PLAYER_TYPE = 0
ORBITER_TYPE = 1
AMIDAR_TYPE = 2
actor_type .byte PLAYER_TYPE, PLAYER_TYPE, PLAYER_TYPE, PLAYER_TYPE
.byte ORBITER_TYPE, AMIDAR_TYPE, AMIDAR_TYPE, AMIDAR_TYPE
.byte AMIDAR_TYPE, AMIDAR_TYPE, AMIDAR_TYPE, AMIDAR_TYPE
.byte AMIDAR_TYPE, AMIDAR_TYPE, AMIDAR_TYPE, AMIDAR_TYPE
actor_init_func_l .byte <init_player, <init_orbiter, <init_amidar
actor_init_func_h .byte >init_player, >init_orbiter, >init_amidar
; Sprite data is interleaved so a simple indexed mode can be used. This is not
; convenient to set up but makes faster accessing because you don't have to
; increment the index register. For example, all the info about sprite #2 can
; be indexed using Y = 2 on the indexed operators, e.g. "lda sprite_active,y",
; "lda sprite_x,y", etc.
;
; Number of sprites must be a power of 2
source_actor_active .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 , $ff ; 1 = active, 0 = skip
source_actor_l
.byte <APPLE_SPRITE9X11
.byte <APPLE_SPRITE9X11
.byte <APPLE_SPRITE9X11
.byte <APPLE_SPRITE9X11
.byte <ATARI_SPRITE9X11
.byte <ATARI_SPRITE9X11
.byte <ATARI_SPRITE9X11
.byte <ATARI_SPRITE9X11
.byte <ATARI_SPRITE9X11
.byte <ATARI_SPRITE9X11
.byte <ATARI_SPRITE9X11
.byte <ATARI_SPRITE9X11
.byte <ATARI_SPRITE9X11
.byte <ATARI_SPRITE9X11
.byte <ATARI_SPRITE9X11
.byte <ATARI_SPRITE9X11
source_actor_h
.byte >APPLE_SPRITE9X11
.byte >APPLE_SPRITE9X11
.byte >APPLE_SPRITE9X11
.byte >APPLE_SPRITE9X11
.byte >ATARI_SPRITE9X11
.byte >ATARI_SPRITE9X11
.byte >ATARI_SPRITE9X11
.byte >ATARI_SPRITE9X11
.byte >ATARI_SPRITE9X11
.byte >ATARI_SPRITE9X11
.byte >ATARI_SPRITE9X11
.byte >ATARI_SPRITE9X11
.byte >ATARI_SPRITE9X11
.byte >ATARI_SPRITE9X11
.byte >ATARI_SPRITE9X11
.byte >ATARI_SPRITE9X11
source_actor_x
.byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 , $ff
source_actor_y
.byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 , $ff
source_end .byte $ff
; [i*7-3 for i in range(40)]
player_col_to_x .byte 0, 3, 10, 17, 24, 31, 38, 45, 52, 59, 66, 73, 80, 87, 94, 101, 108, 115, 122, 129, 136, 143, 150, 157, 164, 171, 178, 185, 192, 199, 206, 213, 220, 227, 234, 241, 248, 248, 248, 248, 248,
;.byte 0, 4, 11, 18, 25, 32, 39, 46, 53, 60, 67, 74, 81, 88, 95, 102, 109, 116, 123, 130, 137, 144, 151, 158, 165, 172, 179, 186, 193, 200, 207, 214, 221, 228, 235, 242, 249, 249, 249, 249, 249
; [i*8-5 for i in range(24)]
player_row_to_y .byte 0, 3, 11, 19, 27, 35, 43, 51, 59, 67, 75, 83, 91, 99, 107, 115, 123, 131, 139, 147, 155, 163, 171, 179
STARTING_LIVES = 3
BONUS_LIFE = 10000
MAX_LIVES = 8
X_MIDPOINT = 3
X_TILEMAX = 7
Y_MIDPOINT = 3
Y_TILEMAX = 8
NOT_VISIBLE = 0
PLAYER_DEAD = 1
PLAYER_ALIVE = 2
PLAYER_EXPLODING = 3
PLAYER_REGENERATING = 4
AMIDAR_NORMAL = 5
ORBITER_NORMAL = 6
GAME_OVER = 255
;
;# Scores
;
DOT_SCORE = $01
box_score .byte 0, $20, $40, $60, $80, $100, $120
add_score nop
sed
clc
adc player_score_l,x
sta player_score_l,x
lda player_score_m,x
adc #0
sta player_score_m,x
lda player_score_h,x
adc #0
sta player_score_h,x
cld
jsr update_score
rts
init_actors_once nop
ldx #0
?1 lda source_actor_active,x
sta actor_active,x
inx
cpx #source_end-source_actor_active
bcc ?1
rts
init_players nop
sta config_num_players
;
init_level nop
ldx level
lda level_enemies,x
tay
lda #$ff
sta actor_active+FIRST_AMIDAR,y
lda #1
?1 sta actor_active+FIRST_AMIDAR-1,y
dey
bne ?1
; clear active players
ldy #0
lda #1
?2 cpy config_num_players
bcs ?3
sta actor_active,y
iny
bne ?2
?3 lda #0
cpy #MAX_PLAYERS
bcs ?4
sta actor_active,y
iny
bne ?3
?4 rts
;
;##### Gameplay initialization
;
;def init_actor():
; # Common initialization params for all actors
; actor_col[zp.current_actor] = MAZE_LEFT_COL
; actor_xpixel[zp.current_actor] = 3
; actor_xfrac[zp.current_actor] = 0
; actor_xspeed[zp.current_actor] = 0
; actor_row[zp.current_actor] = MAZE_BOT_ROW
; actor_ypixel[zp.current_actor] = 3
; actor_yfrac[zp.current_actor] = 0
; actor_yspeed[zp.current_actor] = 0
; actor_input_dir[zp.current_actor] = 0
; actor_updown[zp.current_actor] = TILE_UP
; actor_dir[zp.current_actor] = TILE_UP
; actor_status[zp.current_actor] = NOT_VISIBLE
; actor_frame_counter[zp.current_actor] = 0
; actor_target_col[zp.current_actor] = 0
; actor_input_dir[zp.current_actor] = 0
; actor in X
init_actor nop
lda #MAZE_LEFT_COL
sta actor_col,x
lda #3
sta actor_xpixel,x
sta actor_ypixel,x
lda #0
sta actor_xfrac,x
sta actor_xspeed_l,x
sta actor_xspeed_h,x
sta actor_yfrac,x
sta actor_yspeed_l,x
sta actor_yspeed_h,x
sta actor_input_dir,x
sta actor_frame_counter,x
sta actor_target_col,x
sta actor_input_dir,x
lda #MAZE_BOT_ROW
sta actor_row,x
lda #TILE_UP
sta actor_updown,x
sta actor_dir,x
lda #NOT_VISIBLE
sta actor_status,x
rts
;def init_orbiter():
; init_actor()
; actor_col[zp.current_actor] = ORBITER_START_COL
; actor_row[zp.current_actor] = ORBITER_START_ROW
; actor_dir[zp.current_actor] = TILE_UP
; actor_status[zp.current_actor] = ORBITER_NORMAL
; set_speed(TILE_UP)
; actor in X
init_orbiter nop
jsr init_actor
lda #ORBITER_START_COL
sta actor_col,x
lda #ORBITER_START_ROW
sta actor_row,x
lda #TILE_UP
sta actor_updown,x
sta actor_dir,x
jsr set_speed
lda #ORBITER_NORMAL
sta actor_status,x
rts
;def init_amidar():
; init_actor()
; amidar_index = zp.current_actor - FIRST_AMIDAR - 1 # orbiter always 1st enemy
; actor_col[zp.current_actor] = amidar_start_col[amidar_index]
; actor_row[zp.current_actor] = MAZE_TOP_ROW
; actor_ypixel[zp.current_actor] = 4
; actor_updown[zp.current_actor] = TILE_DOWN
; actor_dir[zp.current_actor] = TILE_DOWN
; actor_status[zp.current_actor] = AMIDAR_NORMAL
; set_speed(TILE_DOWN)
; actor in X
init_amidar nop
jsr init_actor
txa
sec
sbc #FIRST_AMIDAR
sbc #1
tay
lda amidar_start_col,y
sta actor_col,x
lda #MAZE_TOP_ROW
sta actor_row,x
lda #4
sta actor_ypixel,x
lda #TILE_DOWN
sta actor_updown,x
sta actor_dir,x
jsr set_speed
lda #AMIDAR_NORMAL
sta actor_status,x
rts
;def init_player():
; init_actor()
; addr = player_start_col[zp.num_players]
; actor_col[zp.current_actor] = addr[zp.current_actor]
; actor_row[zp.current_actor] = MAZE_BOT_ROW
; actor_status[zp.current_actor] = PLAYER_ALIVE
init_player nop
jsr init_actor
lda config_num_players ; 4 players max,
asl a
asl a
clc
adc current_actor
tay
lda player_start_col,y
sta actor_col,x
lda #MAZE_BOT_ROW
sta actor_row,x
lda #PLAYER_ALIVE
sta actor_status,x
; player_lives[zp.current_actor] = STARTING_LIVES
; player_next_target_score[zp.current_actor] = BONUS_LIFE
lda #STARTING_LIVES
sta player_lives,x
lda #BONUS_LIFE
sta player_next_target_score,x
lda #0
sta player_score_l
sta player_score_h
rts
;def init_actors():
init_actors nop
; get_col_randomizer(amidar_start_col)
lda #<amidar_start_col
sta scratch_addr
lda #>amidar_start_col
sta scratch_addr+1
jsr get_col_randomizer
; get_col_randomizer(round_robin_up)
lda #<round_robin_up
sta scratch_addr
lda #>round_robin_up
sta scratch_addr+1
jsr get_col_randomizer
; get_col_randomizer(round_robin_down)
lda #<round_robin_down
sta scratch_addr
lda #>round_robin_down
sta scratch_addr+1
jsr get_col_randomizer
lda #0
sta round_robin_index
sta round_robin_index+1
; zp.current_actor = 0
; while zp.current_actor <= zp.last_enemy:
; if zp.current_actor <= LAST_PLAYER:
; if zp.current_actor < zp.num_players:
; init_player()
; player_lives[zp.current_actor] = STARTING_LIVES
; player_next_target_score[zp.current_actor] = BONUS_LIFE
; else:
; if zp.current_actor == FIRST_AMIDAR:
; init_orbiter()
; else:
; init_amidar()
; zp.current_actor += 1
; zp.round_robin_index[:] = [0, 0]
lda #$ff
sta current_actor
init_actors_loop inc current_actor
ldx current_actor
lda actor_active,x
bpl ?2 ; negative = end
rts
?2 beq init_actors_loop ; zero = skip
lda actor_type,x
tay
lda actor_init_func_l,y
sta init_actors_smc+1
lda actor_init_func_h,y
sta init_actors_smc+2
init_actors_smc jsr $ffff
jmp init_actors_loop