; a == 1: collision
; hl: if collided with an actor points to the actor hit, otherwise NULL
actor_test_movement:
+ 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
+ push_all
+
+ push hl
+ call rect_tl ; bc = top left point
+ push de
+ pop bc
+ pop hl ; hl = test rect
+
+ ld a, [tmp_rect_mask]
+ call rect_point_test
+ cp a, 1
+ jp z, @rect_collision
+
+ pop_all
+
+@skip_rect:
+ add hl, de ; next rect (de = r_size)
+ dec b
+ jp nz, @rect_test_loop
+
+
+ xor a, a ; no collision
+ ret
+@rect_collision:
+ pop_all
+ ld hl, NULL
+ ld a, 1
ret
call actor_test_movement
pop bc
+ ; TODO: handle collision with another actor
+ ; if hl != NULL
+ cp a, 0
+ ret nz
+
ld a, b
ld [player+act_pos_y], a
ret
; tests if a point is inside r1
- ; a: mask
+ ; does not perform collision mask test
; bc: y/x point
; hl: rectangle
; returns:
; a == 1: inside
; a == 0: not inside
rect_point_test:
- ; check collision mask
- ld d, a
- ld [hl], a
- and a, d
- ; exit if mask is no match
- jp z, @no_collision_mask_match
+ ; top left
+ push hl
+ call rect_tl
+ pop hl
+ ld a, b ; compare y points
+ cp a, d
+ jp nc, @no_collision
+ ld a, c ; compare x position
+ cp a, e
+ jp nc, @no_collision
+
+ ; bottom left
+ push hl
+ call rect_bl
+ pop hl
+
+ ld a, b ; compare y
+ cp a, d
+ jp c, @no_collision
+ ld a, c ; compare x
+ cp a, e
+ jp c, @no_collision
+
+ ; top right
push hl
call rect_tr
pop hl
-
+
+ ; bottom right
+ push hl
+ call rect_br
+ pop hl
+
+
+@collision:
+ ld a, 1
ret
-@no_collision_mask_match:
- xor a, a
+@no_collision:
+ xor a, a ; no collision
+ ret
+
+ ; tests rectangle mask
+ ; inputs:
+ ; a: mask
+ ; hl: rectangle
+ ; returns:
+ ; z-flag: != 0 if mask is ok
+ ; uses: a, c
+rect_test_mask:
+ ld c, a
+ ld a, [hl]
+ and a, c
ret
; removes a rectangle
; temporary rectangle used for collision checks
; during movement
tmp_rect: .adv r_size
+tmp_rect_mask: .adv 1
; current row that is being drawn
map_curr_row: .adv 1