From: Lukas Krickl Date: Wed, 24 Sep 2025 07:50:15 +0000 (+0200) Subject: actor: Added actor -> actor collision X-Git-Url: https://git.krickl.dev/?a=commitdiff_plain;h=153361e91b4750e2a33b18d692cabab815eb1ba2;p=gbrg%2F.git actor: Added actor -> actor collision --- diff --git a/src/actor.s b/src/actor.s index cbb2377..acc72ce 100644 --- a/src/actor.s +++ b/src/actor.s @@ -69,6 +69,11 @@ actor_update_draw_table: dw act_nop dw player_update_and_draw dw act_guard_update_and_draw + +actor_collision_res_table: + dw act_nop + dw player_col_res + dw act_guard_col_res ; calls update for all actors ; and draws them @@ -183,33 +188,131 @@ actor_write_default_collider: ; a == 1: collision ; hl: if collided with an actor points to the actor hit, otherwise NULL actor_test_movement: + push de ld [tmp_rect_mask], a ; check all static rectangles ld hl, rectangles ld b, RECT_MAX ld de, r_size -@rect_test_loop: - ; pre-filter rectangle mask - ld a, [tmp_rect_mask] - call rect_test_mask - jp z, @skip_rect - - ; test all corners of tmp_rect - actor_test_movement_corner rect_bl, @rect_collision - actor_test_movement_corner rect_br, @rect_collision - actor_test_movement_corner rect_tl, @rect_collision - actor_test_movement_corner rect_tr, @rect_collision +@rect_test_loop: + call actor_test_rect + cp a, 0 + jp nz, @rect_collision @skip_rect: add hl, de ; next rect (de = r_size) dec b jp nz, @rect_test_loop + pop de + ld b, ACTS_MAX + + ; start at player actor + ld hl, player +@actor_test_loop: + ld a, [hl] + cp a, 0 ; check if type is 0 + jp z, @skip_actor + + ; check if current actor is in de + ld a, d + cp a, h + jr nz, @test_actor REL + ld a, e + cp a, l + jr z, @skip_actor REL + +@test_actor: + push de + push hl + ld de, act_rect + add hl, de ; hl = rectangle for actor + + call actor_test_rect + cp a, 0 + pop hl + pop de + jp nz, @actor_collision + +@skip_actor: + push bc + ld bc, act_size + add hl, bc ; next actor + pop bc + dec b + jp nz, @actor_test_loop + +@no_collision: + ld hl, NULL xor a, a ; no collision ret @rect_collision: - pop_all + pop de ld hl, NULL ld a, 1 ret +@actor_collision: + ; hl = actor already + ld a, 1 + ret + + ; tests a single rectangle against an actor + ; inputs: + ; tmp_rect: new collision rectangle + ; tmp_rect_mask: mask to test agains + ; hl: rectangle to test + ; returns: + ; a: 1 collision + ; a: 0 no collision +actor_test_rect: + ; pre-filter rectangle mask + ld a, [tmp_rect_mask] + call rect_test_mask + ret z + + ; test all corners of tmp_rect + + actor_test_movement_corner rect_bl, @rect_collision + actor_test_movement_corner rect_br, @rect_collision + actor_test_movement_corner rect_tl, @rect_collision + actor_test_movement_corner rect_tr, @rect_collision + + xor a, a + ret +@rect_collision: + ; actor_test_movement does not pop all when the check + ; passes + pop_all + ld a, 1 + ret + + ; calls collision resolution + ; inputs: + ; de: event origin actor + ; hl: actor collided with +actor_col_res: + ld a, h + or a, l + cp a, 0 + ret z ; do nothing if 0 + + ld a, [hl] + add a, a ; type * 2 as offset into table + + push hl + + ld hl, actor_collision_res_table + ld b, 0 + ld c, a + add hl, bc ; hl = routine ptr + + ld a, [hl+] + ld b, a + ld a, [hl] + ld h, a + ld l, b + + pop bc ; the rotuine wants collider in bc + call_hl + ret diff --git a/src/debug.s b/src/debug.s index 644451f..c0ba348 100644 --- a/src/debug.s +++ b/src/debug.s @@ -106,7 +106,7 @@ dbg_rect_draw: call dbg_rect_draw_ptr ; always draw player rectangle - ld de, player+act_rect + ld de, actors+act_rect call dbg_rect_draw_ptr ret @@ -140,7 +140,6 @@ dbg_rect_draw_ptr: ld a, [de] cp a, 0 jp z, @rect_not_alloced - push de ld a, 4 call oamalloc diff --git a/src/enemy.s b/src/enemy.s index 4c22a67..77903ed 100644 --- a/src/enemy.s +++ b/src/enemy.s @@ -8,6 +8,19 @@ act_enemy_guard: ; inputs: ; de: actor ptr act_guard_update: + ; load position + ld hl, act_pos_y + add hl, de + ld a, [hl+] + ld b, a + ld a, [hl+] + ld c, a + + ; write collision shape + ld hl, act_rect + add hl, de + ld a, RF_ENEMY + call actor_write_default_collider ret ; draws the guard enemy @@ -34,5 +47,21 @@ act_guard_draw: ; combination of update and draw call act_guard_update_and_draw: + push de call act_guard_draw + pop de jp act_guard_update + + ; collision resolution between guard and another actor + ; inputs: + ; de: even origin actor + ; bc: guard +act_guard_col_res: + ld hl, act_hp + add hl, de + + ; test take damage + ld a, [hl] + dec a + ld [hl], a + ret diff --git a/src/map.s b/src/map.s index c966846..6415950 100644 --- a/src/map.s +++ b/src/map.s @@ -253,6 +253,9 @@ l1_objs: modef MOT_SET_PAT, 0, 10, pat_center_grass modef MOT_SET_PAT, 0, 18, pat_center_empty_wall + + modef MOT_RECT, 0, 18, 0x080F + modef MOT_SET_PAT, 0, 0x1E, pat_empty modef MOT_DISABLE_SCROLL, 0, 0x20, 0 modef MOT_NOP, 0, 0xFF, 0 diff --git a/src/player.s b/src/player.s index 2a84024..b7966c3 100644 --- a/src/player.s +++ b/src/player.s @@ -185,9 +185,12 @@ player_try_move: ld de, player call actor_test_movement pop bc + + ; hl should be NULL or an actor ptr + push af + call actor_col_res + pop af - ; TODO: handle collision with another actor - ; if hl != NULL cp a, 0 ret nz @@ -222,3 +225,11 @@ player_draw: player_update_and_draw: call player_draw jp player_update + + ; collision resolution between player + ; and other actor + ; inputs: + ; de: origin actor + ; bc: player +player_col_res: + ret diff --git a/src/video.s b/src/video.s index 81e75e6..ec390d0 100644 --- a/src/video.s +++ b/src/video.s @@ -145,7 +145,7 @@ scroll_up_adjust: pop de push de - cp a, 0xB0 + cp a, 0xA0 call nc, rect_despawn @no_rect_despawn: