; each frame the latest animation is
; updated
+ ; anim_walk_<direction> inputs
+ ; sm_param[0]: frames to walk for
anim_walk_north:
- ret
+ inc bc ; bc = actor y
+ ld d, 0xFF ; walk back
+ jp anim_walk_generic
anim_walk_south:
- ret
+ inc bc ; bc = actor y
+ ld d, 1 ; walk forward
+ jp anim_walk_generic
anim_walk_east:
- ret
+ inc bc
+ inc bc ; bc = actor x
+ ld d, 1 ; walk forward
+ jp anim_walk_generic
anim_walk_west:
+ inc bc
+ inc bc ; bc = actor x
+ ld d, 0xFF ; walk back
+ jp anim_walk_generic
+
+ ; generic version of anim walk
+ ; inputs:
+ ; bc: position to walk in
+ ; d: offset per frame
+anim_walk_generic:
+ sm_load_ptr hl
+ inc hl ; hl = param
+ ld a, [hl]
+ cp a, 0
+ jp z, anim_walk_end
+
+ dec a
+ ld [hl], a ; p0--
+
+ ld a, [bc]
+ add a, d
+ ld [bc], a ; y++
ret
+ ; aborts walk
+ ; inputs:
+ ; none
+anim_abort_walk:
+ sm_load_ptr hl
+ inc hl
+
+ ; inputs:
+ ; hl: sm_param[0]
+anim_walk_end:
+ dec hl ; hl = sm_state
+ ld a ,smt_end_turn
+ ld [hl], a
+ ret
#define ANIM_STEP_UP 0xFF
#define ANIM_STEP_RIGHT 1
+#define ANIM_PLAYER_WALK_FRAMES 16
+
; actor type enum
.se 0
; null actor type = nop
.se 1
.de smt_end_turn, 1
.de smt_player_poll_inputs, 1
+.de smt_player_go_north, 1
+.de smt_player_go_south, 1
+.de smt_player_go_east, 1
+.de smt_player_go_west, 1
@noassert
#endmacro
+ ; loads the state machine ptr
+ ; into $1
+ ; inptuts:
+ ; $1: register (hl, de, bc)
+#macro sm_load_ptr
+ ld $1, state_machine
+#endmacro
; restore hl
pop hl
- ; play move animation
- ; and skip inputs if it is still
- ; ongoing
- ld a, [end_turn]
- cp a, 0
- jr z, @no_anim REL ; do not play anim if turn is not ended
-
- call anim_move
- cp a, 0
- jp nz, @skip_input
- call who_next ; next actor's turn
- call anim_clear
- jp nz, @skip_input
-@no_anim:
-
- ; set collision mask
- ld a, RF_WALL | RF_DOOR | RF_ACTOR
- ld [ct_mask], a
-
- ; anim_target_y = y movement target
- ; anim_target_x = x movement target
- ; load tmp and +1 with the current position by
- ; default
- ld a, [hl+]
- ld [anim_target_y], a
- ld a, [hl]
- dec hl
- ld [anim_target_x], a
-
- ; input handling
- input_held BTNDOWN
- jr z, @notdown REL
-
- ; set animation params
- ld a, ANIM_MOVE_TILE_SIZE
- ld [anim_move_y], a
- ld a, ANIM_STEP_DOWN
- ld [anim_step_y], a
-
- ; set expected offset
- ld a, ANIM_MOVE_TILE_SIZE
- add a, [hl]
- ld [anim_target_y], a
-
- call play_noise
- turn_finish
-@notdown:
-
- input_held BTNUP
- jr z, @notup REL
-
- ; set animation params
- ld a, ANIM_MOVE_TILE_SIZE
- ld [anim_move_y], a
- ld a, ANIM_STEP_UP
- ld [anim_step_y], a
-
- ; set expected offset
- ld a, ANIM_MOVE_TILE_SIZE_N
- add a, [hl]
- ld [anim_target_y], a
-
- call play_noise
- turn_finish
-@notup:
-
-
- input_held BTNLEFT
- jr z, @notleft REL
-
- ; set animation params
- ld a, ANIM_MOVE_TILE_SIZE
- ld [anim_move_x], a
- ld a, ANIM_STEP_LEFT
- ld [anim_step_x], a
-
- ; set expected offset
- ld a, ANIM_MOVE_TILE_SIZE_N
- inc hl
- add a, [hl]
- dec hl
- ld [anim_target_x], a
-
- call play_noise
- turn_finish
-@notleft:
-
- input_held BTNRIGHT
- jr z, @notright REL
-
- ; set animation params
- ld a, ANIM_MOVE_TILE_SIZE
- ld [anim_move_x], a
- ld a, ANIM_STEP_RIGHT
- ld [anim_step_x], a
-
- ; set expected offset
- ld a, ANIM_MOVE_TILE_SIZE
- inc hl
- add a, [hl]
- dec hl
- ld [anim_target_x], a
-
- call play_noise
- turn_finish
-@notright:
-
-@action_buttons:
-
- input_just BTNA
- jr z, @nota REL
-
- ; reduce hp by 1
- ld a, 1
- ; make sure we do not mess with hl
- push hl
- ; hl = player_y right now
- push de ; de will get used in take damage
- call player_take_damage
- ; call for UI redraw
- ld a, UI_REDRAW_HP
- ld [ui_flags], a
- pop de
- pop hl
-@nota:
-
- input_just BTNB
- jr z, @notb REL
-
- ; gain 1 hp
- ld a, 1
- ; make sure we do not mess with hl
- push hl
- ; hl = player_y right now
- inc hl
- inc hl
- inc hl ; hl = player_hp
- call player_gain_resource
- ; call for UI redraw
- ld a, UI_REDRAW_HP
- ld [ui_flags], a
- pop hl
-
-@notb:
- ; sotre x in e
- ld a, [hl]
- ld e, a
-
- ld a, [anim_target_y]
- add a, 8
- ld d, a ; d = target y + 8 to center on tile
- ld a, [anim_target_x]
- add a, 8
- ld e, a ; e = target x + 8 to center on tile
- call player_collision_check
-
@update_end:
@skip_input:
; hl should be player_y here
; performs player collision checks
; inputs:
- ; hl: player ptr
- ; de: y/x position used for check
+ ; bc: actor ptr
+ ; de: y/x position offset
player_collision_check:
+
+ ; set collision mask
+ ld a, RF_WALL | RF_DOOR | RF_ACTOR
+ ld [ct_mask], a
+
+ ; load actor y/x into de
+ inc bc ; bc = actor y
+ ld a, [bc]
+ add a, d ; y + offset
+
+ ld d, a ; d = target y
+ inc bc ; bc = actor x
+ ld a, [bc]
+ add a, e ; x + offset
+ ld e, a ; e = target x
+
; if any collision happens now
; we stop the animation
- push hl ; need to save hl
call collision_tile
ld h, a ; store original a in h for now
ld a, h ; restore original a for next check
and a, RF_WALL | RF_ACTOR
- pop hl
jr z, @no_collision REL
- ; clear anim memory
- call anim_clear
+ ; abort walk state
+ call anim_abort_walk
jr @skip REL
@no_collision:
; call z, player_tile_update_rf_flags
; to store their current state and call small re-usable routines
; at the end of a chain the state should always be 0
+
; table of all states
; expected inputs:
; bc: actor_ptr
- ; de: state machine ptr
state_table:
dw sm_nop
dw sm_end_turn
dw sm_player_poll_inputs
+ dw anim_walk_north
+ dw anim_walk_south
+ dw anim_walk_east
+ dw anim_walk_west
sm_nop:
ret
sm_end_turn:
call sm_clear
+ turn_finish
+ call who_next
ret
; clears the state machine
sm_clear:
xor a, a
- ld hl, state_machine
- ld a, [hl+]
- ld a, [hl+]
- ld a, [hl+]
+ sm_load_ptr hl
+ ld [hl+], a
+ ld [hl+], a
+ ld [hl], a
ret
sm_player_poll_inputs:
+ ; bc = actor type
+
+ sm_load_ptr hl
+
+ ; input handling
+ input_held BTNDOWN
+ jr z, @notdown REL
+
+ ; set animation params
+ ld a, smt_player_go_south
+ ld [hl+], a ; set next state
+ ld a, ANIM_PLAYER_WALK_FRAMES
+ ld [hl], a ; set param[0]
+
+ ; perform collision check
+ ld d, ANIM_PLAYER_WALK_FRAMES
+ ld e, 0
+ call player_collision_check
+
+ ret
+@notdown:
+
+ input_held BTNUP
+ jr z, @notup REL
+
+ ; set animation params
+ ld a, smt_player_go_north
+ ld [hl+], a ; set next state
+ ld a, ANIM_PLAYER_WALK_FRAMES
+ ld [hl], a ; set param[0]
+
+
+ ; perform collision check
+ ld d, 0xFF & 0 - ANIM_PLAYER_WALK_FRAMES
+ ld e, 0
+ call player_collision_check
+
+ ret
+@notup:
+
+ input_held BTNLEFT
+ jr z, @notleft REL
+
+ ; set animation params
+ ld a, smt_player_go_west
+ ld [hl+], a ; set next state
+ ld a, ANIM_PLAYER_WALK_FRAMES
+ ld [hl], a ; set param[0]
+
+ ; perform collision check
+ ld d, 0
+ ld e, 0xFF & 0 - ANIM_PLAYER_WALK_FRAMES
+ call player_collision_check
+
+ ret
+@notleft:
+
+ input_held BTNRIGHT
+ jr z, @notright REL
+
+ ; set animation params
+ ld a, smt_player_go_east
+ ld [hl+], a ; set next state
+ ld a, ANIM_PLAYER_WALK_FRAMES
+ ld [hl], a ; set param[0]
+
+ ; perform collision check
+ ld d, 0
+ ld e, ANIM_PLAYER_WALK_FRAMES
+ call player_collision_check
+
+ ret
+@notright:
+
ret
; loads initial state if