enemy.c0;enemy.cNHhdB@LLLPTEXTCWIE.;i/#include #include #include #include #include "enemy.h" #include "bullet.h" #include "player.h" #include "map.h" #include "sprite.h" #include "global.h" #include "addrs.h" #include "assert.h" typedef struct enemyentry { u_char type; long x,y; // Position of nasty u_char *startpos; // Starting position of enemy u_char HP; long long1, long2; // Use varies depending on type u_char byte1, byte2, byte3, byte4; // struct enemyentry *next; } enemy; static enemy *enemies = NULL; static short swingangle[180]; extern u_char screen; static void FindElecDirn(enemy* ptr); void FindEnemies(void) { u_char x,y,tile,i; u_char *mapptr = (u_char*)mapaddr+(screen*20*15); enemy *temp; // Calculate angles for swinging spike ball for (i=0;i<180;i++) swingangle[i] = 2048 + ((1137*DJsin((i*8192)/360))>>12); // Wipe any existing enemies while (enemies!=NULL) { temp = enemies; enemies = enemies->next; free(temp); } for (y=0;y<15;y++) { for (x=0;x<20;x++) { tile = *(mapptr++); if (tile==2 || tile==40 || tile==43 || tile==49 || tile==56 || tile==70) { temp = (enemy*)malloc(sizeof(enemy)); temp->x = x<<20; temp->y = y<<20; temp->startpos = mapptr-1; temp->next = enemies; enemies = temp; if (tile==2) { // Goblin enemies->type = 1; enemies->HP = 23; enemies->byte1 = enemies->byte2 = enemies->byte3 = enemies->byte4 = 0; } if (tile==40) { // Electric sphere enemies->type = 2; enemies->HP = 27; enemies->byte1 = enemies->byte2 = enemies->byte3 = enemies->byte4 = 0; enemies->long1 = 0; } if (tile==43) { // Jumping goblin enemies->type = 3; enemies->HP = 19; enemies->byte1 = enemies->byte2 = enemies->byte3 = enemies->byte4 = 0; enemies->long1 = -1; } if (tile==49) { // Goblin gunner enemies->type = 4; enemies->HP = 35; enemies->byte1 = rand() % 40; } if (tile==56) { // Fish enemies->type = 5; enemies->HP = 25; enemies->byte1 = enemies->byte2 = enemies->byte3 = enemies->byte4 = 0; } if (tile==70) { // Spike ball enemies->type = 6; enemies->HP = 255; enemies->byte1 = rand() % 180; enemies->long1 = (x<<20) + (6<<16); enemies->long2 = (y<<20) + (6<<16); } } } } } void Enemies(GsOT* OT) { enemy *enemyptr = enemies; GsSPRITE enemyspr; long x, y; u_char temp, i; long angle; InitSpr(&enemyspr); while (enemyptr!=NULL) { switch (enemyptr->type) { case 1: case 3: // Goblin if (enemyptr->byte1==0) enemyptr->x+=(2<<16); else enemyptr->x-=(2<<16); // Check if goblin has walked into wall or off screen if (Solid(enemyptr->x>>16, enemyptr->y>>16) || enemyptr->x>>16<0 || enemyptr->x>>16>304) { if (enemyptr->byte1==0) enemyptr->x-=(2<<16); else enemyptr->x+=(2<<16); enemyptr->byte1^=1; } if (enemyptr->type==1) { // Check if goblin should turn round to avoid going off edge if (enemyptr->byte1==0 && !Solid((enemyptr->x>>16)+16, (enemyptr->y>>16)+16)) enemyptr->byte1 = 1; if (enemyptr->byte1==1 && !Solid((enemyptr->x>>16)-16, (enemyptr->y>>16)+16)) enemyptr->byte1 = 0; } else { // Make 'im jump enemyptr->y+=(enemyptr->long1+=16384); if (Solid(enemyptr->x>>16, enemyptr->y>>16)) { if (enemyptr->long1>0) { enemyptr->y>>=20; enemyptr->y<<=20; enemyptr->long1=-(6<<16); } else { enemyptr->y>>=20; enemyptr->y+=1; enemyptr->y<<=20; enemyptr->long1 = 0; } } } if (enemyptr->byte2<2) { // Move his legs if (enemyptr->byte3-- == 0) { enemyptr->byte3 = 6; enemyptr->byte2^=1; } } else { if ((enemyptr->byte4--) == 0) enemyptr->type = 255; } // Set up sprite data enemyspr.w = enemyspr.h = 16; enemyspr.x = enemyptr->x>>16; enemyspr.y = enemyptr->y>>16; CalcSprPos(enemyspr, 640+(48*enemyptr->byte1)+(16*enemyptr->byte2), 208); break; case 2: // Electric sphere if (enemyptr->long1 == -1) FindElecDirn(enemyptr); if (enemyptr->byte4 == 0) { // Move in given direction. if ((enemyptr->long1+=8192) > (2<<16)) enemyptr->long1 = (2<<16); switch (enemyptr->byte1) { case 0: enemyptr->y-=enemyptr->long1; break; case 2: enemyptr->y+=enemyptr->long1; break; case 1: enemyptr->x+=enemyptr->long1; break; case 3: enemyptr->x-=enemyptr->long1; break; } } else { // Drop to the floor (dead). if ((enemyptr->long1+=32768) > (8<<16)) enemyptr->long1 = (8<<16); enemyptr->y+=enemyptr->long1; } if (Solid(enemyptr->x>>16, enemyptr->y>>16) || enemyptr->x>>16<0 || enemyptr->x>>16>304 || enemyptr->y>>16<0 || enemyptr->y>>16>224) { // Sphere has moved into an illegal area. // Move back to align with tiles. switch (enemyptr->byte1) { case 0: enemyptr->y>>=20; enemyptr->y++; enemyptr->y<<=20; break; case 2: enemyptr->y>>=20; enemyptr->y<<=20; break; case 1: enemyptr->x>>=20; enemyptr->x<<=20; break; case 3: enemyptr->x>>=20; enemyptr->x++; enemyptr->x<<=20; break; } if (enemyptr->byte4==0) FindElecDirn(enemyptr); else { // Dead sphere has hit ground, splat. enemyptr->type = 255; AddBlood(enemyptr->x>>16, enemyptr->y>>16); AddBlood((enemyptr->x>>16)+3, enemyptr->y>>16); AddBlood((enemyptr->x>>16)-3, enemyptr->y>>16); AddBlood((enemyptr->x>>16)+6, enemyptr->y>>16); AddBlood((enemyptr->x>>16)-6, enemyptr->y>>16); } } // Make it flash if (enemyptr->byte3-- == 0) { enemyptr->byte3 = 6; if (enemyptr->byte2++ == 2) enemyptr->byte2 = 0; } // Set up sprite data enemyspr.w = enemyspr.h = 16; enemyspr.x = enemyptr->x>>16; enemyspr.y = enemyptr->y>>16; CalcSprPos(enemyspr, 640+(16*enemyptr->byte2), 176); break; case 4: // Goblin gunner GetPlPos(&x, &y); // Narrow angle down to within 90 degrees but keep note of quadrant. // up/left - 0, up/right - 1, down/left - 2, down/right - 3. temp = 0; if (x>enemyptr->x) {temp |= 1; x = x-enemyptr->x;} else x = enemyptr->x-x; if (y>enemyptr->y) {temp |= 2; y = y-enemyptr->y;} else y = enemyptr->y-y; if (x>>12 == 0) angle = 32768; else angle = y / (x>>12); switch (temp) { case 0: if (angle>16384) enemyptr->byte2 = 0; // Vertical else if (angle>6144) enemyptr->byte2 = 15; // 2:1 else if (angle>3072) enemyptr->byte2 = 14; // 1:1 else if (angle>1024) enemyptr->byte2 = 13; // 1:2 else enemyptr->byte2 = 12; // Horizontal break; case 1: if (angle>16384) enemyptr->byte2 = 0; // As above else if (angle>6144) enemyptr->byte2 = 1; else if (angle>3072) enemyptr->byte2 = 2; else if (angle>1024) enemyptr->byte2 = 3; else enemyptr->byte2 = 4; break; case 2: if (angle>16384) enemyptr->byte2 = 8; else if (angle>6144) enemyptr->byte2 = 9; else if (angle>3072) enemyptr->byte2 = 10; else if (angle>1024) enemyptr->byte2 = 11; else enemyptr->byte2 = 12; break; case 3: if (angle>16384) enemyptr->byte2 = 8; else if (angle>6144) enemyptr->byte2 = 7; else if (angle>3072) enemyptr->byte2 = 6; else if (angle>1024) enemyptr->byte2 = 5; else enemyptr->byte2 = 4; break; } if ((enemyptr->byte1--) == 0) { // Fire bullet enemyptr->byte1 = 39; angle = (enemyptr->byte2*256) + ((rand() & 127)-64); if (angle<0) angle+=4096; if (angle>=4096) angle-=4096; AddBullet(enemyptr->x+(15<<16),enemyptr->y+(15<<16),angle,1); } // Set up sprite data enemyspr.w = enemyspr.h = 32; enemyspr.x = enemyptr->x>>16; enemyspr.y = enemyptr->y>>16; CalcSprPos(enemyspr, 640+(enemyptr->byte2*32), 224); break; case 5: // Fish if (enemyptr->byte1==0) enemyptr->x+=(2<<16); else enemyptr->x-=(2<<16); // Check if fish has walked into wall or off screen if (Solid(enemyptr->x>>16, enemyptr->y>>16) || enemyptr->x>>16<0 || enemyptr->x>>16>304) { if (enemyptr->byte1==0) enemyptr->x-=(2<<16); else enemyptr->x+=(2<<16); enemyptr->byte1^=1; } if (enemyptr->byte2<2) { // Animate fish if (enemyptr->byte3-- == 0) { enemyptr->byte3 = 6; enemyptr->byte2^=1; } } else { if ((enemyptr->byte4--) == 0) enemyptr->type = 255; } // Set up sprite data enemyspr.w = enemyspr.h = 16; enemyspr.x = enemyptr->x>>16; enemyspr.y = enemyptr->y>>16; CalcSprPos(enemyspr, 640+(48*enemyptr->byte1)+(16*enemyptr->byte2), 192); break; case 6: // Swinging spike ball // Swing ball if ((++enemyptr->byte1) == 180) enemyptr->byte1 = 0; // Plot chain enemyspr.w = enemyspr.h = 4; x = enemyptr->long1; y = enemyptr->long2; CalcSprPos(enemyspr, 640, 280); for (i=0;i<18;i++) { x+=DJsin(swingangle[enemyptr->byte1])<<6; y-=DJcos(swingangle[enemyptr->byte1])<<6; enemyspr.x = x>>16; enemyspr.y = y>>16; GsSortFastSprite(&enemyspr, OT, 14); } enemyspr.x-=6; enemyspr.y-=6; enemyptr->x = x-(6<<16); enemyptr->y = y-(6<<16); enemyspr.w = enemyspr.h = 16; CalcSprPos(enemyspr, 640, 256); break; } if (enemyptr->type!=255) GsSortFastSprite(&enemyspr, OT, 13); enemyptr = enemyptr->next; } } static void FindElecDirn(enemy* ptr) { // Calculate new direction electric sphere should move in. long plx,ply; GetPlPos(&plx, &ply); if (ptr->byte1==0 || ptr->byte1==2) { // Move horizontally if (plx>ptr->x) ptr->byte1 = 1; else ptr->byte1 = 3; } else { // Move vertically if (ply>ptr->y) ptr->byte1 = 2; else ptr->byte1 = 0; } ptr->long1 = 0; } u_char GetHit(long x, long y) { enemy *enemyptr = enemies; char sizex,sizey; u_char retval = 0; long ex,ey; while (enemyptr!=NULL) { // Find size and position of enemy sizex = sizey = 16; if (enemyptr->type == 4) {sizex = 32; sizey = 32;} if (enemyptr->type == 255) {sizex = -126; sizey = -126;} ex = enemyptr->x>>16; ey = enemyptr->y>>16; // If player lies in bounding box return 1 if (x+16>ex && x-sizexey && y-sizeynext; } return retval; } u_char CheckHitEnemy(long x, long y) { enemy *enemyptr = enemies; u_char sizex,sizey,xoffset,yoffset; u_char retval = 0; long ex,ey; while (enemyptr!=NULL && retval==0) { // Calculate size and offset within square surrounding sprite. sizex = sizey = 16; xoffset = yoffset = 0; if (enemyptr->type==4) {xoffset = 8; yoffset = 8;} if (enemyptr->type==6 || enemyptr->type==255) sizex = sizey = 0; ex = enemyptr->x>>16; ey = enemyptr->y>>16; if (x>ex+xoffset && x-sizexey+yoffset && y-sizeyHP--) == 0) { switch (enemyptr->type) { case 1: case 3: *(enemyptr->startpos) = 14; enemyptr->byte2 = 2; enemyptr->byte4 = 15; break; case 2: *(enemyptr->startpos) = 14; enemyptr->byte1 = 2; enemyptr->byte4 = 1; enemyptr->long1 = 0; break; case 4: *(enemyptr->startpos) = 45; *(enemyptr->startpos+1) = 46; *(enemyptr->startpos+20) = 47; *(enemyptr->startpos+21) = 48; enemyptr->type = 255; break; case 5: *(enemyptr->startpos) = 53; enemyptr->byte2 = 2; enemyptr->byte4 = 15; break; } } retval = 1; } enemyptr = enemyptr->next; } return retval; }ZZRNavigator 3.01 %enemy.cr Itemstsx.harozentallerETEXTCWIE.cache27443.gifNetscape Navigator 3.01 %ˋϳC>H Monaco4,D4,DP%&$ZZRsx3jRMPSRMWBB*LR