;############## Calcuzap by Patrick Davidson - collision detection ;############## Sets the first object for collision check by structure ; Takes HL pointing to the following four bytes: ; X-coordinate, Y-coordinate, pointer to image (height, then width) ; This will be considered as object 2 below set_collision_check_object: ld a,(hl) ; X inc hl ld c,(hl) ; Y inc hl #ifdef TI84CE ld hl,(hl) ld (image_2),hl ld de,(hl) #else ld e,(hl) inc hl ld d,(hl) ; DE -> image ex de,hl ; HL -> image ld (image_2),hl ld e,(hl) ; height inc hl ld d,(hl) ; width #endif ;############## Sets the first object for collision check ; A = X, C = Y, E = height, D = width ld (ccx+1),a ld a,c ld (ccy+1),a ld a,d ld (ccw+1),a ld a,e ld (cch+1),a ret ;############## Test for collisions between two objects ; ; Carry flag set if they collided, clear if they didn't ; Takes HL pointing to the following four bytes: ; X-coordinate, Y-coordinate, pointer to image (height, then width) collision_check: ;############## Ensure that X1 < X2 + W2 ld a,(hl) ; A = X1 inc hl ld b,(hl) ; B = Y1 ld (ccy1+1),hl inc hl #ifdef TI84CE ld hl,(hl) ; HL -> image height #else ld e,(hl) inc hl ld d,(hl) ; DE -> H1 ex de,hl ; HL -> H1 #endif ld c,(hl) ; C = H1 ccx: sub 3 ; A = X1 - X2 jr c,cc1 ; (X1 < X2) --> (X1 < X2 + W2) ccw: cp 3 ret nc ; Exit if (X1 - X2) >= W2 jr cc2 ; (X2 <= X1) --> (X2 < X1 + W1) ;############## Ensure that X2 < X1 + W1 cc1: neg ; A = X2 - X1 (which is > 0) inc hl ; HL -> W1 cp (hl) dec hl ; HL -> H1 ret nc ; Exit if (X2 - X1) >= W1 ;############## Ensure that Y1 < Y2 + H2 cc2: ld a,b ; A = Y1 ccy: sub 3 ; A = Y1 - Y2 jr c,cc3 ; (Y1 < Y2) --> (Y1 < Y2 + H2) cch: cp 3 ; Carry set if (Y1 - Y2) < H2 ret nc ; End of testing (last cond. certain jr exact_check ; since Y2 <= Y1, due to jr c,cc3) ;############## Ensure that Y2 < Y1 + H1 cc3: neg ; A = Y2 - Y1 (which is > 0) cp c ret nc ; Carry set if (Y2 - Y1) < H1 ;############## Pixel-exact collision check, apply Y coordinate to comparison window exact_check: ld (image_1),hl ; HL -> H1 ex de,hl ; DE -> H1 ccy1: ld hl,0 ; HL -> e_y (1) ld a,(ccy+1) ; A = Y2 sub (hl) ; compute Y2 - Y1, carry set if Y2 < Y1 push hl ; save e_y pointer jr c,exact_check_object_2_above ;############## Pixel-exact collision check, object 1 is above ld b,a ; B = count of rows to skip ex de,hl ; HL -> H1 ld a,(hl) ; A = H1 sub b ; B = image 1 height from collision start ld c,a ; C = image 1 height from collision start inc hl ld a,(hl) ; A = width in double pixels inc hl ; skip width #ifdef TI84CE ld de,0 #else ld d,0 #endif add a,a add a,a ; A = width in bytes ld e,a ; DE = width in bytes xor a or b jr z,exact_same_y exact_skip_rows_1: add hl,de djnz exact_skip_rows_1 exact_same_y: ld (image_1_row),hl ld hl,(image_2) ld a,(hl) ; HL = image 2 height cp c jr c,exact_1_above_height ; branch if C holds larger value ld a,c ; A = smaller value exact_1_above_height: ld (exact_check_outer-1),a ; shorter of two heights (comparison size) inc hl inc hl ld (image_2_row),hl jr exact_check_compare_x_coords ;############## Pixel-exact collision check, object 2 is above exact_check_object_2_above: neg ; A = distance by which object 2 is above ld b,a inc de inc de ld (image_1_row),de ; compare image 1 starting with its first row ld hl,(image_2) ld a,(hl) ; A = image 2 height sub b ; A = image 2 height from comparison start ld c,a ; C = image 2 height from comparison start inc hl ld a,(hl) ; A = width of image 2 in double pixels inc hl #ifdef TI84CE ld de,0 #else ld d,0 #endif add a,a add a,a ; A = width in bytes ld e,a ; DE = width in bytes exact_skip_rows_2: add hl,de djnz exact_skip_rows_2 ld (image_2_row),hl ld hl,(image_1) ld a,(hl) ; A = image 1 height cp c jr c,exact_2_above_height ; branch if C holds larger value ld a,c ; A = smaller value exact_2_above_height: ld (exact_check_outer-1),a ; shorter of two heights (comparison size) ;############## Pixel-exact collision check, apply X coordinate to comparison window exact_check_compare_x_coords: pop hl dec hl ; HL -> e_x (on image 1) ld a,(ccx+1) ; A = X2 sub (hl) ; compute X2 - X1, carry set if X2 < X1 jr c,exact_check_object_2_left ;############## Pixel-exact collision check, object 1 is to the left ld b,a ; B = initial skip in double pixels add a,a ; A = count of initial pixels to skip add a,a ; A = count of initial bytes to skip #ifdef TI84CE ld de,0 #else ld d,0 #endif ld e,a ; DE = count of initial bytes to skip ld hl,(image_1_row) add hl,de ld (image_1_row),hl ld hl,(image_1) inc hl ld a,(hl) ; A = W1 sub b ; A = remaining width of 1 ld c,a ld a,(ccw+1) ; A = W2 cp c jr c,exact_check_go ; branch if C holds larger value (A already smaller) ld a,c ; A = smaller value jr exact_check_go ;############## Pixel-exact collision check, object 2 is to the left exact_check_object_2_left: neg ld b,a ; B = initial skip in double pixels add a,a ; A = count of initial pixels to skip add a,a ; A = count of initial bytes to skip #ifdef TI84CE ld de,0 #else ld d,0 #endif ld e,a ; DE = count of initial bytes to skip ld hl,(image_2_row) add hl,de ld (image_2_row),hl ld a,(ccw+1) ; A = W2 sub b ; A = remaining width of 2 ld hl,(image_1) inc hl cp (hl) ; compare with width of 1 jr c,exact_check_go ld a,(hl) ; A = smaller value ;############## Calculate horizontal skip between rows, A = overlap width exact_check_go: ld (exact_check_inner-1),a ld b,a ; B = overlap width ld a,(ccw+1) sub b ; A = W2 - overlap (skip on image 2) add a,a add a,a ld (exact_check_second_skip+1),a ld hl,(image_1) inc hl ld a,(hl) sub b ; A = W1 - overlap (skip on image 1) add a,a add a,a ld (exact_check_first_skip+1),a ;############## Pixel-by-pixel check main loops ld hl,(image_1_row) ld de,(image_2_row) ld b,1 ; number of rows to check (compare height) exact_check_outer: push bc ld b,1 ; number of double pixels per row to check exact_check_inner: ld a,(hl) ; check one pixel from (HL) inc hl or (hl) inc hl jr z,exact_check_first_blank ld a,(de) ; check one pixel from (DE) ld c,a inc de ld a,(de) inc de or c jr z,exact_check_first_no_match pop bc scf ; both nonzero -> signal collision ret exact_check_first_blank: inc de ; skip a pixel in (DE) if (HL) blank inc de exact_check_first_no_match: ld a,(hl) ; check one pixel from (HL) inc hl or (hl) inc hl jr z,exact_check_second_blank ld a,(de) ; check one pixel from (DE) ld c,a inc de ld a,(de) inc de or c jr z,exact_check_second_no_match pop bc scf ; both nonzero -> signal collision ret exact_check_second_blank: inc de ; skip a pixel in (DE) if (HL) blank inc de exact_check_second_no_match: djnz exact_check_inner exact_check_first_skip: ld bc,0 add hl,bc exact_check_second_skip: ld bc,0 ex de,hl add hl,bc ex de,hl pop bc djnz exact_check_outer xor a ret