From cfafb3c6dc6a7ea9bfcef05e86f852c3b1527e8b Mon Sep 17 00:00:00 2001 From: Lukas Krickl Date: Sun, 21 Sep 2025 06:27:57 +0200 Subject: [PATCH] collision: added basic stubs for collision rectangles --- src/defs.s | 47 ++++++++++++--------- src/macros.inc | 14 +++++- src/main.s | 1 + src/map.s | 1 + src/mapobj.s | 5 +++ src/rectangle.s | 110 ++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 157 insertions(+), 21 deletions(-) create mode 100644 src/rectangle.s diff --git a/src/defs.s b/src/defs.s index dab08a2..84bce88 100644 --- a/src/defs.s +++ b/src/defs.s @@ -32,6 +32,27 @@ #define UI_TILE_WIDTH 32 #define UI_TILE_HEIGHT 4 + + ; rectangle collision flags +.se 1 + ; collides with player +.de RF_PLAYER, 1 + ; is a generic wall +.de RF_WALL, 2 + ; collides with enemy +.de RF_ENEMY, 4 + + ; rectangle struct +.se 0 + ; if flags == 0 the rectangle is free +.de r_flags, 1 +.de r_pos_y, 1 +.de r_pos_y_hi, 1 +.de r_pos_x, 1 +.de r_h, 1 +.de r_w, 1 +.de r_size, 0 + ; actor type enum .se 0 @@ -53,10 +74,16 @@ ; custom parameter .de act_p0, 1 + + ; state parameter +.de act_state, 1 ; stats .de act_hp, 1 .de act_ac, 1 + + ; every actor has a collision rectangle +.de act_rectangle, r_size .de act_size, 0 @@ -107,26 +134,6 @@ .de mo_row, 1 .de mo_dat, 2 .de mo_size, 0 - - ; rectangle collision flags -.se 1 - ; collides with player -.de RF_PLAYER, 1 - ; is a generic wall -.de RF_WALL, 2 - ; collides with enemy -.de RF_ENEMY, 4 - - ; rectangle struct -.se 0 - ; if flags == 0 the rectangle is free -.de r_flags, 1 -.de r_pos_y, 1 -.de r_pos_y_hi, 1 -.de r_pos_x, 1 -.de r_h, 1 -.de r_w, 1 -.de r_size, 0 ; gameplay control flags diff --git a/src/macros.inc b/src/macros.inc index f687d22..e29fe98 100644 --- a/src/macros.inc +++ b/src/macros.inc @@ -177,11 +177,23 @@ $1: ; $4: hp ; $5: armor #macro actdef - .db $1, $2, $3 + .db $1, $2 + ; placeholder for y, row and x ; since those are set at runtime .db 0, 0, 0 + + .db $3 + + ; placeholder for state parameter + ; this is set by the actor update routine as needed + .db 0 + .db $4, $5 + + ; placeholder for collision rectangle + ; since those are runtime values + .db 0, 0, 0, 0, 0, 0 #endmacro ; defines a map object diff --git a/src/main.s b/src/main.s index 544376a..e1ff764 100644 --- a/src/main.s +++ b/src/main.s @@ -66,6 +66,7 @@ main: #include "math.s" #include "game.s" #include "actor.s" +#include "rectangle.s" #include "tiles.inc" #include "text.s" diff --git a/src/map.s b/src/map.s index 57f64d9..86430a8 100644 --- a/src/map.s +++ b/src/map.s @@ -236,6 +236,7 @@ l1_map: l1_objs: modef MOT_SET_PAT, 0, 3, pat_center_empty_wall + modef MOT_RECT, 0, 3, 0 modef MOT_SET_PAT, 0, 8, pat_center_grass modef MOT_SET_PAT, 0, 10, pat_center_empty_wall modef MOT_SET_PAT, 0, 0x1E, pat_empty diff --git a/src/mapobj.s b/src/mapobj.s index 98487c0..930b653 100644 --- a/src/mapobj.s +++ b/src/mapobj.s @@ -107,6 +107,11 @@ mo_enable_scroll: ret ; spawns a collision rectangle + ; the origin of a rectangle is the bottom left + ; dat1: nnnn0000: y offset from row in 8 pixel increments + ; 0000nnnn: height in 8 pixel increments + ; dat2: nnnn0000: x offset from row in 8 pixel increments + ; 0000nnnn: width in 8 pixel increments ; inputs: ; de: map object ptr mo_rect: diff --git a/src/rectangle.s b/src/rectangle.s new file mode 100644 index 0000000..f41e049 --- /dev/null +++ b/src/rectangle.s @@ -0,0 +1,110 @@ + + ; attempts to add a rectangle + ; to the rectangle buffer + ; if no slots are availabel it will simply be skipped + ; this function always sets y_hi to 0 + ; inputs: + ; a: flags + ; b/c: y/x position + ; d/e: h/w +rect_try_add: + push af + push bc + push de + call rect_find_slot + ld a, h + or a, l + cp a, 0 + ; if hl == 00 exit + jp z, @exit + + pop de + pop bc + pop af + + ; write flags + ld [hl+], a + + ; write y + ld a, b + ld [hl+], a + + ; wirte y hi + xor a, a + ld [hl+], a + + ; wirte x + ld a, c + ld [hl+], a + + ; write h + ld a, d + ld [hl+], a + + ; write w + ld a, e + ld [hl], a + + ret +@exit: + pop de + pop bc + pop af + ret + + ; attempts to find a rectangle slot where + ; flags == 0 (unused) + ; returns: + ; hl: 0000 -> no slot + ; hl: ptr -> slot +rect_find_slot: + ld hl, rectangles + ld de, r_size + ld b, RECT_MAX + +@loop: + ; hl = flags + ld a, [hl] + ; if flags is 0 we ret + cp a, 0 + ret z + + add hl, de + dec b + jr nz, @loop REL + + ; if nothing was found ld NULL + ld hl, 0 + ret + + ; tests if any point + ; of r1 is inside r2 + ; inputs: + ; de: r1 + ; hl: r2 + ; returns: + ; a == 1: inside + ; a == 0: not inside +rect_test: + ld a, [de] + ld b, a + ld a, [hl] + ; check if masks have a match + ; otherwise skip + and a, b + cp a, 0 + jp z, @no_collision_mask_match + + ret +@no_collision_mask_match: + ld a, 0 + ret + + ; tests if a point is inside r1 + ; bc: y/x point + ; hl: rectangle + ; returns: + ; a == 1: inside + ; a == 0: not inside +rect_point_test: + ret -- 2.30.2