**************************************************************************** **************************************************************************** ** ** Phoenix (Collision detection) ** ** Copyright 2004 by Patrick Davidson. This software may be freely ** modified and/or copied with no restrictions. There is no warranty. ** ** by Patrick Davidson (pad@calc.org, http://pad.calc.org/) ** ** Last updated August 9, 2004 ** **************************************************************************** **************************************************************************** ******************************************** TEST FOR COLLISIONS * * This routine tests two objects for collisions. It returns with the zero * flag set (and D0 = 0) if there is no collision, and the zero flag clear * (and D1 = -1) if there is a collision. It first checks whether the * rectangular boundaries of the objects overlap. If they do, it then draws * the images themselves to test for overlap of actual images. * * This routine is guaranteed to preserve A3-A6 and D3-D7. All other * registers may be changed. * * Parameters: * * A3 -> Bullet, enemy, or enemy bullet structure of one object * A4 -> Bullet, enemy, or enemy bullet structure of the other * * The overlap testing is done by drawing the objects into a special buffer * for testing. The buffer is 8 bytes (64 pixels) wide. The first step in * the test is to clear the area that object A3 would be in, which is the * center longword (the object will always start at X coordinate of 24). * Next, object A4 is drawn into this buffer (at an adjusted X-coordinate) * and the object in A3 is tested against it by ANDing its data with anything * that may have been written in the test area. * ******** Test_Collision: move.w e_y(a4),d0 ; Test Y-coord overlap blt no_collision add.w e_h(a4),d0 sub.w b_y(a3),d0 ble.s no_collision sub.w e_h(a4),d0 sub.w b_h(a3),d0 bge.s no_collision move.w e_x(a4),d0 ; Test X-coord overlap add.w e_w(a4),d0 sub.w b_x(a3),d0 ble.s no_collision sub.w e_w(a4),d0 sub.w b_w(a3),d0 bge.s no_collision lea cdt+2(a5),a0 ; Clear temp buffer for A3 moveq #0,d1 ; D1 = 0 lea image_table(pc),a2 ; A2 -> image table move.w e_y(a3),d0 lsl.w #3,d0 add.w d0,a0 ; A0 = A3's pos in temp buffer move.l a0,-(sp) ; D3 = A3's pos in temp buffer move.w e_h(a3),d0 subq.w #1,d0 ; D0 = # lines to clear - 1 lclr: move.l d1,(a0) ; Clear a line addq.l #8,a0 ; A0 -> next line dbra d0,lclr move.w e_x(a4),d0 ; Draw first sprite (A4) sub.w b_x(a3),d0 add.w #24,d0 ; D0 = X4 - X3 + 24 move.w e_y(a4),d1 ; A1 = Y4 move.w e_image(a4),d2 bsr.s Move_Sprite move.l (sp)+,a1 ; Test image (A3) with it move.w e_h(a3),d0 subq.w #1,d0 ; D0 = # lines to clear - 1 move.w e_image(a3),d1 ; D1 = image handle from (A3) lea 2(a2,d1.w),a0 ; A2 -> (A3) image data loop_col_det: move.l (a0)+,d1 ; D1 = line's image data and.l (a1),d1 ; D1 = collision mask bne.s collision ; if nonzero, collision addq.l #8,a1 ; A1 -> next line dbra d0,loop_col_det no_collision: moveq #0,d0 rts collision: moveq #-1,d0 rts ******************************************** PUT SPRITE VIA MOVE * * This routine draws a sprite in the collision-detection testing buffer. * The sprite is done simply by copying its sprite data over the screen; * saving any original image is not important. * ******** Move_Sprite: lea 0(a2,d2.w),a0 tst.w d1 blt.s no_collision move.w d0,d2 ;D0 = X coordinate and.w #15,d0 lsl.w #3,d1 ;D1 = Y coordinate lea 0(a5,d1.w),a1 add.w #cdt,a1 lsr.w #4,d2 add.w d2,d2 add.w d2,a1 move.w (a0)+,d2 ;A0 -> Sprite data subq.w #8,d0 bgt.s ms_ShiftRight beq.s ms_alignedOK ms_ShiftLeft: neg.w d0 ms_ShiftLeft_: move.l (a0)+,d1 lsl.l d0,d1 eor.l d1,(a1) addq.l #8,a1 dbra d2,ms_ShiftLeft_ rts ms_alignedOK: move.l (a0)+,d1 move.l d1,(a1) addq.l #8,a1 dbra d2,ms_alignedOK rts ms_ShiftRight: move.l (a0)+,d1 lsr.l d0,d1 move.l d1,(a1) addq.l #8,a1 dbra d2,ms_ShiftRight rts