#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
; 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
.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
; $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
#include "math.s"
#include "game.s"
#include "actor.s"
+#include "rectangle.s"
#include "tiles.inc"
#include "text.s"
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
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:
--- /dev/null
+
+ ; 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