From: Lukas Krickl Date: Mon, 8 Sep 2025 21:00:38 +0000 (+0200) Subject: animation: Refactored animation code X-Git-Url: https://git.krickl.dev/?a=commitdiff_plain;h=ec0655a85fe61d4d31e14f6f599880da98464069;p=gbrg%2F.git animation: Refactored animation code The new system allows defintion of tables. Tables can be loaded and contain up to 3 objects. --- diff --git a/src/animation.s b/src/animation.s index c8fad8a..604be83 100644 --- a/src/animation.s +++ b/src/animation.s @@ -1,9 +1,25 @@ -player_anim_header: - anim_header 2, ANIM_HEAD_F_LOOP, 1, player_anim_table, NULL - player_anim_table: - anim_ent 0x8C, 0x00, 0, 0 - anim_ent 0x8C, 0x00, 0, 0 + anim_ent 0, 8, 0x8C, OAM_FXFLIP + anim_ent 0, 0, 0x8E, OAM_FXFLIP + anim_ent 0, 0, 0x00, 0 + dw player_anim_table + + + ; translates tile to screen + ; inputs: + ; $1: Y/X offset + ; $2: register containing scroll + ; a: tile position +#macro tile_to_scrn + mul16 a + add a, $1 + sub a, $2 +#endmacro + + ; performs no drawing +unit_nop_draw: + ldnull bc + ret ; calls unit's draw function @@ -57,42 +73,135 @@ get_left_tile_offset2: ld a, 8 ret - ; draws the unit's tile - ; based on the set oam tile - ; and the currently set offset - ; each actor has 2 tiles drawn here - ; tile 1 is the selected tile - ; tile 2 is the tile next (+1) to the selected tile + ; draws a unit's animation table + ; draws all 3 tables based on animation timer + ; and animation max value (first item in table) ; inputs ; de: actor unit_draw: - push de - ld hl, act_oam_tile - add hl, de ; hl = tile - ld a, [hl+] + ; load anim entries + ld hl, act_anim_table + add hl, de ; hl = entry 1 + ld a, [hl+] + push af + ld a, [hl] + ld h, a + pop af + ld l, a + push hl + pop bc ; bc = anim talbe entry - ld b, a ; base tile - ld a, [hl+] - ld c, a ; flags - ld a, [hl] ; a = tile offset - add a, b ; base tile + offset - ld b, a ; b = real tile - - ld a, c ; c = oam flags for offset call - call get_left_tile_offset1 - push bc - call unit_generic_draw - - ; draw same tile again - pop bc - pop de - push de - inc b - inc b ; b+=2 - ld a, c ; a = flags - call get_left_tile_offset2 - call unit_generic_draw - pop de - - ldnull bc + call unit_draw_obj + call unit_draw_obj + call unit_draw_obj + + ; load next anim table + ld hl, act_anim_table + ld a, [bc] + ld [hl+], a + inc bc + ld a, [bc] + ld [hl], a ret + + ; draws a single object + ; in the current animation table + ; inputs: + ; de: actor + ; bc: anim table entry + ; returns: + ; bc: next entry +unit_draw_obj: +#define TMP_SCROLL_Y scratch +#define TMP_SCROLL_X scratch+1 +#define TMP_A scratch+2 + ; skip if tile is 0x00 + inc bc + inc bc + ld a, [bc] + dec bc + dec bc + cp a, 0 + jp z, @skip_ent + + push de + + ; hl = pos y + ld hl, act_pos_y + add hl, de + push hl + pop de ; de = pos y + + push bc + push de + + call load_scroll + ld a, b + ld [TMP_SCROLL_Y], a + ld a, c + ld [TMP_SCROLL_X], a + + call load_unit_obj + + pop de + + ; set y position + ld a, [TMP_SCROLL_Y] + ld b, a ; b = y scroll + ld a, [de] + tile_to_scrn OBJ_OFF_Y, b ; scroll offset + ld [TMP_A], a + + ; apply anim entry y offset + pop bc + ld a, [bc] + push bc + ld b, a + ld a, [TMP_A] + add a, b ; a += y offset + ; write result to obj + ld [hl+], a + + + ; set x position + inc de + ld a, [TMP_SCROLL_X] + ld c, a ; c = scroll x + ld a, [de] + tile_to_scrn OBJ_OFF_X, c + ld [TMP_A], a + + ; apply anim entry x offset + pop bc + inc bc ; next entry + ld a, [bc] + push bc + ld b, a + ld a, [TMP_A] + add a, b ; a += x offset + ; write result to obj + ld [hl+], a + + pop bc + inc bc ; bc = tile index + ; write tile from table + ld a, [bc] + ld [hl+], a + + ; write flags + inc bc + ld a, [bc] + ld [hl+], a + inc bc + + pop de + ret +@skip_ent: + inc bc + inc bc + inc bc + inc bc + ret +#undefine TMP_SCROLL_Y +#undefine TMP_SCROLL_X +#undefine TMP_A diff --git a/src/defs.s b/src/defs.s index 39bf082..70e2e86 100644 --- a/src/defs.s +++ b/src/defs.s @@ -189,15 +189,7 @@ ; can be used for animations or other relevant timers ; state switching may change this value. .de act_rt_timer, 1 - - ; sub-tile drawing vars - ; during this animation the actor is already technically in its new - ; location. the real location offset can be calculated with - ; the st_time in the actor if sub tile enable is set - ; ab0de000: direction bits (a == 1 -> up; b == 1 -> down; d == 1 -> left; e == 1 -> right) - ; 00c00000: c: sub tile enabled -.de act_rt_sub_tile, 1 - + ; stats1 .de act_level, 1 .de act_hp, stat_size @@ -226,31 +218,7 @@ ; returns: ; bc: null .de act_draw, 2 - - ; act_oam_tile + flags - ; if using generic draw: - ; 2 tiles are used - ; tile 1 is the tile specified here - ; tile 2 is the tile following tile 1 - ; flags are used for both tiles - ; optional: - ; tile + flags may be a pointer to a - ; tile table. This can be implemented as needed -.de act_oam_tile, 1 -.de act_oam_flags, 1 - - ; offset from the currently selected tile - ; animations work by applying this offset - ; to the selected base tile - ; this allows runtime configuration - ; of the frames - ; e.g. the offset could be switched to 0/2 based - ; on the current frame count - ; to make an idel animation - ; note: the offset should always be an even number - ; due to the use of 8x16 objects -.de act_rt_oam_tile_offset, 1 - +.de act_anim_table, 2 .de act_size, 0 ; actor save game data @@ -348,30 +316,17 @@ .se 0 .de action_st_action_ptr, 2 .de action_size, 0 - -; animation header struct -.se 0 - ; how many objects can an animation draw - ; valid values are 1, 2, 3, 4 -.de anim_header_objs, 1 -.de anim_header_flags, 1 -.de anim_header_frames, 1 -.de anim_header_table, 1 -.de anim_header_next, 2 ; next animation if not looping - -; animation header flags -.se 1 - ; loop the animation - ; if set to 0 return to next animation -.de ANIM_HEAD_F_LOOP, 1 - ; animation entry struct +; an animation table is *always* +; 3 entries followed by a next ptr +; if the tile is 0x00 the entry is not rendered .se 0 +.de anim_ent_y_offset, 1 +.de anim_ent_x_offset, 1 .de anim_ent_oam_tile, 1 .de anim_ent_oam_flags, 1 -.de anim_ent_x_offset, 1 -.de anim_ent_y_offset, 1 +.de anim_ent_size, 0 ; special text commands diff --git a/src/macros.inc b/src/macros.inc index 27a21f2..f446c0e 100644 --- a/src/macros.inc +++ b/src/macros.inc @@ -157,14 +157,10 @@ ; defines actor meta data call for actor ; inputs: ; $1: draw call - ; $2: default tiles - ; $3: default oam flags + ; $2: animation header ptr #macro act_def_meta dw $1 - .db $2 - .db $3 - ; tile offset - .db 0 + dw $2 #endmacro ; define an actor without state @@ -187,7 +183,6 @@ .db 0, 0, 0 ; act_rt_collided_with dw 0 - .db 0 ; act_rt_sub_tile ; act_rt_action_dat1/2 .db 0, 0 @@ -281,27 +276,12 @@ ld b, a #endmacro - ; animation header - ; inputs: - ; $1: obj count (1, 2, 3, 4) - ; $2: flags - ; $3: number of frames - ; $4: animation table - ; $5: next animation -#macro anim_header - .db $1 - .db $2 - .db $3 - dw $4 - dw $5 -#endmacro - ; animation entry ; inputs: - ; $1: tile - ; $2: oam flags - ; $3: x offset - ; $4: y offset + ; $1: y offset + ; $2: x offset + ; $3: tile + ; $4: oam flags #macro anim_ent .db $1 .db $2 diff --git a/src/main.s b/src/main.s index 9478d30..6585a40 100644 --- a/src/main.s +++ b/src/main.s @@ -63,6 +63,7 @@ main: #include "map.s" #include "math.s" +#include "animation.s" #include "roompatterns.s" #include "mapgen.s" #include "state.s" @@ -83,7 +84,6 @@ main: #include "shoot.s" #include "action_menu.s" #include "select_menu.s" -#include "animation.s" ; fill bank .fill 0xFF, 0x4000 - $ diff --git a/src/player.s b/src/player.s index 876c9e9..1c37328 100644 --- a/src/player.s +++ b/src/player.s @@ -29,14 +29,6 @@ unit_player_update: cp a, 0 ret nz - push de - ld hl, act_oam_flags - add hl, de - ld a, [hl] - or a, OAM_FXFLIP - ld [hl], a - pop de - ; check if the player is currently ; on a convered tile or not push de @@ -331,7 +323,7 @@ unit_player: act_stat_def1 1, 3, 1, 1 act_stat_def2 1, 1, 90, 1 act_st_def st_unit_player_update, st_unit_idle - act_def_meta player_draw, 0x8C, OAM_FPRIO + act_def_meta player_draw, player_anim_table st_unit_player_update: st_def 0x00, unit_player_update, st_unit_player_update diff --git a/src/unit.s b/src/unit.s index a64eff7..7951891 100644 --- a/src/unit.s +++ b/src/unit.s @@ -45,148 +45,6 @@ units_update: jr nz, @loop REL ret - - ; adjust an object's position - ; based on sub-tile state - ; inputs: - ; de: actor - ; hl: object in shadow oam -unit_generic_draw_adjust_subtile: - ; check if actor is in sub-tile mode - push hl - push de - - ld hl, act_rt_sub_tile - add hl, de - ld a, [hl] ; a = rt_sub_tile value - pop de ; de = actor st_time - pop hl ; hl = obj - ld b, a ; b = rt_sub_tile value - cp a, 0 - ; if this value is 0 we are not moving - jp z, @done - - ld a, [de] ; load timer - div8 a ; a = timer/8 giving us a pixel offset - ld c, a ; c = timer/8 - - ; test bit 7 for up - bit 7, b - jr z, @not_up REL - ld a, [hl] ; a = obj y - add a, c ; a += offset - ld [hl], a -@not_up: - - ; test bit 6 for down - bit 6, b - jr z, @not_down REL - ld a, [hl] - sub a, c ; a -= offset - ld [hl], a -@not_down: - - inc hl ; hl = x position - - ; test bit 4 for left - bit 4, b - jr z, @not_left REL - ld a, [hl] - add a, c ; a += offset - ld [hl], a -@not_left: - - ; test bit 3 for right - bit 3, b - jr z, @not_right REL - ld a, [hl] - sub a, c ; a += offset - ld [hl], a -@not_right: - -@done: - - ret - - ; translates tile to screen - ; inputs: - ; $1: Y/X offset - ; $2: register containing scroll - ; a: tile position -#macro tile_to_scrn - mul16 a - add a, $1 - sub a, $2 -#endmacro - - ; performs no drawing -unit_nop_draw: - ldnull bc - ret - - ; draws any unit - ; inputs: - ; de: actor - ; a: x-offset for tiles - ; b: tile1 - ; c: flags -unit_generic_draw: -#define TMP_OAMFLAG_PRIO scratch -#define TMP_X_OFFSET scratch+1 - ld [TMP_X_OFFSET], a ; save for later - - push de ; save actor - - xor a, a - ld [TMP_OAMFLAG_PRIO], a - - push bc - - ld hl, act_pos_y - add hl, de ; hl = act_pos_y - push hl - - call load_scroll - call load_unit_obj - - pop de ; de = act_pos_y - - ; set y pos - ld a, [de] - tile_to_scrn OBJ_OFF_Y, b - ld [hl+], a - - ; set x pos - inc de - ld a, [de] - tile_to_scrn OBJ_OFF_X, c - ld c, a - ld a, [TMP_X_OFFSET] - add a, c - ld [hl+], a - - pop bc ; bc = inputs again - - ; set tile - ld a, b - ld [hl+], a - - - ; set flags - ld a, [TMP_OAMFLAG_PRIO] - or a, c - ld [hl], a - - dec hl - dec hl - dec hl ; object - 3 go back to start - pop de - call unit_generic_draw_adjust_subtile - - ldnull bc - ret -#undefine TMP_OAMFLAG_PRIO -#undefine TMP_X_OFFSET ; sets player turn taken flag unit_set_player_turn_taken: @@ -425,35 +283,6 @@ unit_collides_with_any_other: ret #undefine scratch_loop_i - ; sets st_unit_delay_to_active speed to unit's move speed - ; (STAT_MAX-stat_calc_speed) - ; inputs: - ; de: actor - ; a: mask for rt_sub_tile - ; rt_subtile |= a -unit_set_delay_to_active_speed: - push de - ld hl, act_rt_sub_tile - add hl, de ; hl = ptr to sub_tile - - ld b, a - ld a, [hl] - or a, b ; apply the mask - ld [hl], a ; store new value - - ; get movement speed - pop de - call stat_calc_speed - ld de, st_unit_delay_to_active ; de == st_time - ; this overwrites the wait time - ; by calculating the movement speed - ; and subtracting it from STAT_MAX - ld b, a ; b = current speed - ld a, STAT_MAX - ; a - b - sub a, b - ld [de], a ; delay timer is now speed - ret ; moves a unit up ; moves are aborted @@ -466,12 +295,6 @@ unit_set_delay_to_active_speed: ; actor initiative based on tile flags ; actor position unit_try_move_up: - ; enable subtile up - ld a, 0b10100000 - push de - call unit_set_delay_to_active_speed - pop de - ; y - 1 unit_test_collision dec b, CF_COLLISION @@ -492,12 +315,6 @@ unit_try_move_up: ret unit_try_move_down: - ; enable subtile down - push de - ld a, 0b01100000 - call unit_set_delay_to_active_speed - pop de - ; y + 1 unit_test_collision inc b, CF_COLLISION @@ -514,12 +331,6 @@ unit_try_move_down: ret unit_try_move_left: - ; enable subtile left - push de - ld a, 0b00110000 - call unit_set_delay_to_active_speed - pop de - ; x - 1 unit_test_collision dec c, CF_COLLISION @@ -536,12 +347,6 @@ unit_try_move_left: ret unit_try_move_right: - ; enable subtile right - push de - ld a, 0b00101000 - call unit_set_delay_to_active_speed - pop de - ; x + 1 unit_test_collision inc c, CF_COLLISION @@ -615,13 +420,6 @@ unit_scroll_center: ; returns: ; bc: new state unit_switch_to_active: - push de - ld hl, act_rt_sub_tile - add hl, de - xor a, a - ld [hl], a ; clear sub_tile values - pop de - ld hl, act_st_active add hl, de ; hl = st_active ptr ld a, [hl+] diff --git a/src/unit_demo.s b/src/unit_demo.s index b71443d..1af0db1 100644 --- a/src/unit_demo.s +++ b/src/unit_demo.s @@ -1,3 +1,20 @@ +unit_demo_guard_anim_table: + anim_ent 0, 0, 0x88, 0 + anim_ent 0, 8, 0x8A, 0 + anim_ent 0, 0, 0x00, 0 + dw unit_demo_guard_anim_table + +unit_demo_dog_anim_table: + anim_ent 0, 0, 0x90, 0 + anim_ent 0, 8, 0x92, 0 + anim_ent 0, 0, 0x00, 0 + dw unit_demo_dog_anim_table + +unit_demo_hazmat_anim_table: + anim_ent 0, 0, 0x94, 0 + anim_ent 0, 8, 0x96, 0 + anim_ent 0, 0, 0x00, 0 + dw unit_demo_hazmat_anim_table unit_demo_1_init: ldnull bc @@ -21,15 +38,7 @@ unit_demo_guard: act_stat_def1 1, 3, 1, 1 act_stat_def2 1, 1, 32, 1 act_st_def st_unit_demo_1_cpu_update, st_unit_idle - act_def_meta unit_draw, 0x88, OAM_FPRIO - -unit_demo_agent: - st_def 0x00, unit_demo_1_init, st_unit_demo_1_cpu_update - act_def ACT_T_DEMO_1, 0, 9, 9, 0 - act_stat_def1 1, 1, 1, 1 - act_stat_def2 1, 1, 32, 1 - act_st_def st_unit_demo_1_cpu_update, st_unit_idle - act_def_meta unit_draw, 0x8C, OAM_FPRIO + act_def_meta unit_draw, unit_demo_guard_anim_table unit_demo_dog: st_def 0x00, unit_demo_1_init, st_unit_demo_1_cpu_update @@ -37,7 +46,7 @@ unit_demo_dog: act_stat_def1 1, 2, 1, 1 act_stat_def2 1, 1, 32, 1 act_st_def st_unit_demo_1_cpu_update, st_unit_idle - act_def_meta unit_draw, 0x90, OAM_FPRIO + act_def_meta unit_draw, unit_demo_dog_anim_table unit_demo_hazmat: @@ -46,7 +55,7 @@ unit_demo_hazmat: act_stat_def1 1, 1, 1, 1 act_stat_def2 1, 1, 32, 1 act_st_def st_unit_demo_1_cpu_update, st_unit_idle - act_def_meta unit_draw, 0x94, OAM_FPRIO + act_def_meta unit_draw, unit_demo_hazmat_anim_table st_unit_demo_1_cpu_update: