From 27a27e16414b090f2b8178333529018ca00ea072 Mon Sep 17 00:00:00 2001 From: Lukas Krickl Date: Sun, 2 Feb 2025 06:30:32 +0100 Subject: [PATCH] state: Removed old player input handling - replaced with new state machine The new implmenetation is a more modular approach to handling actor states. It works by swapping a simple state parameter out and calling functions from a table. The table to call is still left up to the actors. --- src/animation.s | 51 +++++++++++++- src/defs.s | 6 ++ src/macros.inc | 7 ++ src/player.s | 182 ++++++------------------------------------------ src/state.s | 90 ++++++++++++++++++++++-- 5 files changed, 166 insertions(+), 170 deletions(-) diff --git a/src/animation.s b/src/animation.s index f432c89..76b49f2 100644 --- a/src/animation.s +++ b/src/animation.s @@ -2,15 +2,60 @@ ; each frame the latest animation is ; updated + ; anim_walk_ 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 diff --git a/src/defs.s b/src/defs.s index 19791ac..bf16bbf 100644 --- a/src/defs.s +++ b/src/defs.s @@ -55,6 +55,8 @@ #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 @@ -205,3 +207,7 @@ .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 diff --git a/src/macros.inc b/src/macros.inc index ec9a653..2682689 100644 --- a/src/macros.inc +++ b/src/macros.inc @@ -98,3 +98,10 @@ @noassert #endmacro + ; loads the state machine ptr + ; into $1 + ; inptuts: + ; $1: register (hl, de, bc) +#macro sm_load_ptr + ld $1, state_machine +#endmacro diff --git a/src/player.s b/src/player.s index 1c6afd1..44b18da 100644 --- a/src/player.s +++ b/src/player.s @@ -80,162 +80,6 @@ player_update: ; 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 @@ -336,12 +180,27 @@ player_update: ; 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 @@ -366,11 +225,10 @@ player_collision_check: 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 diff --git a/src/state.s b/src/state.s index f330d11..bb62b89 100644 --- a/src/state.s +++ b/src/state.s @@ -2,32 +2,112 @@ ; 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 -- 2.30.2