**************************************************************************** **************************************************************************** ** ** Phoenix (Enemies) ** ** Copyright 2000 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 June 4, 2000 ** **************************************************************************** **************************************************************************** ******************************************** MOVE THE ENEMIES * * This enemy routine moves every enemy. It uses the enemy's type in each * enemy structure to select a routine from the table of actual enemy * routines. The table itself, as well as the routines, are in the file * ENEMIES2.ASM. * * Each enemy routine will be called with A4 pointing to that enemy's enemy * structure, and A3 pointing to the position in the coordinate table for * that enemy (the coordinate table has 4 bytes per enemy, and is mainly used * to specify locations for enemies that are in formation). The D7 register * is used as the loop counter; the order in which the enemies are processed * is reversed at each frame, so the low bit will be different at each frame * for a specific enemy. * * The enemy handling routines should preserver the A3, A4, and D7 registers. * Their purpose is to move the enemy by updating its coordinates, and make * other changes to the data as needed (e.g. changing the image if the enemy * is animated). It should NOT draw the enemy to the screen. * ******** Move_Enemies: btst #0,cycle_counter+3(a5) beq.s enemies_opposite move.l xy_pointer(a5),a3 ;A3 -> standard coordinates lea enemies_data(a5),a4 ;A4 -> enemy structure moveq #num_en-1,d7 loop_move_enemies: move.w (a4),d0 beq.s me_no_enemy_here jsr Move_Enemies(pc,d0.w) me_no_enemy_here: lea e_size(a4),a4 addq.l #4,a3 dbra d7,loop_move_enemies rts enemies_opposite: move.l xy_pointer(a5),a3 add.l #4*num_en,a3 lea enemies_data_end(a5),a4 moveq #num_en-1,d7 _loop_move_enemies: lea -e_size(a4),a4 subq.l #4,a3 move.w (a4),d0 beq.s b_me_no_enemy_here jsr Move_Enemies(pc,d0.w) b_me_no_enemy_here: dbra d7,_loop_move_enemies rts ******************************************** ENEMY TABLE & CONTROL ROUTINES INCLUDE enemies2.asm INCLUDE megaboss.asm ******************************************** DRAW/ERASE THE ENEMIES * * Quite simply, this runs through the enemy array, and draws each enemy on * the screen using the standard sprite display code. * ******** Draw_Enemies: lea enemies_data(a5),a4 moveq #num_en-1,d7 loop_draw_enemies: tst.w (a4) beq.s ed_no_enemy_here move.w e_y(a4),d1 move.w e_x(a4),d0 move.w e_image(a4),d2 bsr Xor_Sprite_D2 ed_no_enemy_here: lea e_size(a4),a4 dbra d7,loop_draw_enemies rts ******************************************** HANDLE COLLISIONS WITH ENEMIES * * This routine tests for collisions between enemies and bullets fired by the * player. It tests every possible pair of such objects. It now uses the * standard collision detection code in COLLIDE.ASM, which will test if the * actual images overlap. * * Whenever a collision is detected, the enemy is normally damaged by the * amount specified in the bullet, and the bullet is destroyed. The only * exception is the special bullet (with a negative type) which is not * destroyed. * * When the enemy is destroyed, the e_dstry field is used to locate the * destruction routine, which will be executed to destroy the enemy, normally * by changing it's type to an explosion (refer to EDESTROY.ASM for details). * * The first step of the routine is to sort the enemies into left, center, and * right lists depending on which part of the screen they are in. Then, each * bullet is processed by testing it for collisions with enemies in the * appropriate lists. * ******** Enemy_Collisions: moveq #-1,d0 ;D0 = Count in left list - 1 moveq #-1,d1 ;D1 = Count in center list - 1 moveq #-1,d2 ;D2 = Count in right list - 1 lea left_list_data(a5),a0 ;A0 -> position in left list lea center_list_data(a5),a1 ;A1 -> position in center list lea right_list_data(a5),a2 ;A2 -> position in right list lea enemies_data(a5),a4 ;A4 -> position in enemy list moveq #num_en-1,d4 ;D4 = Enemy counter place_enemies: tst.w e_y(a4) ble.s place_done move.w e_x(a4),d3 btst #7,d3 bne.s place_right add.w e_w(a4),d3 subq.w #1,d3 btst #7,d3 beq.s place_left place_center: move.l a4,(a1)+ addq.w #1,d1 bra.s place_done place_right: move.l a4,(a2)+ addq.w #1,d2 bra.s place_done place_left: move.l a4,(a0)+ addq.w #1,d0 place_done: lea e_size(a4),a4 dbra d4,place_enemies move.w d0,left_list_size(a5) move.w d1,center_list_size(a5) move.w d2,right_list_size(a5) lea bullets_data(a5),a3 ;A3 = Bullet pointer move.w num_b(a5),d3 ;D3 = Bullet counter EC_process_bullets: tst.w (a3) beq.s EC_no_bullet lea center_list_size(a5),a2 bsr.s EC_scan_enemies move.w e_x(a3),d6 btst #7,d6 bne.s EC_bullet_not_left lea left_list_size(a5),a2 bsr.s EC_scan_enemies add.w e_w(a3),d6 subq.w #1,d6 btst #7,d6 beq.s EC_no_bullet EC_bullet_not_left: lea right_list_size(a5),a2 bsr.s EC_scan_enemies EC_no_bullet: lea b_size(a3),a3 dbra d3,EC_process_bullets EC_rts: rts Destroy_Base: EC_scan_enemies: ;Scan enemy list at (A2) move.w (a2)+,d4 blt.s EC_rts EC_scan_loop: move.l (a2)+,a4 tst.w (a4) ble.s EC_no_enemy move.l a2,d7 bsr Test_Collision move.l d7,a2 beq.s EC_no_enemy move.w b_dmg(a3),d0 sub.w d0,e_dmg(a4) bgt.s EC_not_destroyed move.w e_dstry(a4),d0 jsr Destroy_Base(pc,d0.w) EC_not_destroyed: clr.w (a3) addq.l #4,sp bra.s EC_no_bullet EC_no_enemy: dbra d4,EC_scan_loop rts