home *** CD-ROM | disk | FTP | other *** search
- /*
-
- ------------------------------------------------------------------
-
- Black Nebula
-
- File : enemy.c
- Programmer: Colin Adams
- Date: 6/5/91
- Last Modified : 10/6/91
-
- Description:
-
- Updates the enemy objects in space (movement and rotations)
- Will be fixed a lot for the next version.
-
- ------------------------------------------------------------------
-
- */
-
- #include "3d.h"
-
- extern short U_rot;
-
- #define DecreaseVelocity(obj) { if(obj->velocity>4)obj->velocity--; }
-
- #define IncreaseMissileVelocity(obj) {if(obj->velocity<30)obj->velocity++;}
- #define DecreaseMissileVelocity(obj) {if(obj->velocity>20)obj->velocity--;}
-
- extern void AddNewObject(short, short, short, short);
- extern int player_missiles;
-
- int player_scale, player_score;
- short num_active[NO_OBJ_TYPES];
-
- /* ------------------------------------------------------------------
- Coding
- ------------------------------------------------------------------
- */
-
- void IncreaseVelocity(object *obj)
- /* some ships move much faster than others.... */
- {
- register int max;
-
- switch(obj->type)
- {
- case SHUTTLE: max = 5; break;
- case KRAIT: max = 11; break;
- case GECKO: max = 8; break;
- case THARGOID: max = 11; break;
- case MAMBA: max = 8; break;
- }
-
- if(obj->velocity<max) obj->velocity++;
- }
-
- int GetTargetAngle(object *obj, short px, short pz)
- {
- register int o, angle, tempint;
- register char quad;
- int temp, ex = obj->trans_x+obj->centre_x, ez = obj->trans_z+obj->centre_z;
- float depth, temp2;
- int d;
-
- tempint = px-ex;
- depth = tempint * tempint;
- tempint = pz-ez;
- depth += tempint * tempint;
-
- if(ex>px)
- {
- o = ex - px;
- if(ez>pz)
- quad = 4;
- else
- {
- if(pz==ez) return 0;
- quad = 1;
- }
- }
- else
- {
- if(px==ex)
- {
- if(ez<pz)
- return 90;
- else
- return 270;
- }
-
- o = px - ex;
-
- if(ez>pz)
- quad = 3;
- else
- {
- if(pz==ez) return 180;
- quad = 2;
- }
- }
-
- temp = o * 4096;
- temp2 = fsqrt(depth);
-
- d = temp/temp2;
-
- if(d>4096) d = 4096; /* to fix small errors */
-
- angle = anti_sin[d];
-
- switch(quad)
- {
- case 1: angle = 90 - angle; break;
- case 2: angle = 90 + angle; break;
- case 3: angle = 180 + (90-angle); break;
- case 4: angle += 270; break;
- }
- return angle;
- }
-
- int GetPointAngle(int *de, short px, short pz)
- {
- register int o, angle, tempint;
- register char quad;
- int temp;
- float depth, temp2;
- int d;
-
- tempint = px-ex;
- depth = tempint * tempint;
- tempint = pz-ez;
- *de = (depth += tempint * tempint);
-
- if(ex>px)
- {
- o = ex - px;
- if(ez>pz)
- quad = 4;
- else
- {
- if(pz==ez) return 0;
- quad = 1;
- }
- }
- else
- {
- if(px==ex)
- {
- if(ez<pz)
- return 90;
- else
- return 270;
- }
-
- o = px - ex;
-
- if(ez>pz)
- quad = 3;
- else
- {
- if(pz==ez) return 180;
- quad = 2;
- }
- }
-
- temp = o * 4096;
- temp2 = fsqrt(depth);
-
- d = temp/temp2;
-
- if(d>4096) d = 4096; /* to fix small errors */
-
- angle = anti_sin[d];
-
- switch(quad)
- {
- case 1: angle = 90 - angle; break;
- case 2: angle = 90 + angle; break;
- case 3: angle = 180 + (90-angle); break;
- case 4: angle += 270; break;
- }
- return angle;
- }
-
- void LaunchMissile(object *obj)
- /* this object would like to launch a missile at the player... */
- {
- register int i;
- int tx = obj->centre_x + obj->trans_x + FastCos(200, obj->heading);
- int tz = obj->centre_z + obj->trans_z - FastSin(200, obj->heading);
-
- for(i=0; i<MAX_OBJECTS; i++)
- {
- register object *missile;
-
- if(!obj_free[ENEMYMISSILE][i])
- {
- int difficult = player_score>>12;
- register int rand = getrandom(0, 30-difficult) - (30-difficult)/2;
- int heading = obj->heading + rand;
-
- if(heading<0)
- heading += 360;
- else if(heading>359)
- heading -= 360;
-
- missile = &obj_types[ENEMYMISSILE][i];
- Translate_Obj_Abs(missile, tx, obj->trans_y+obj->centre_y, tz);
- missile->i_am_dying = missile->lastdrawme = missile->lastdraw2 = 0;
- missile->velocity = 25 + difficult;
- missile->timeinflight = 0;
- missile->heading = heading;
- Rotate_Obj_Abs(missile, 0, heading, 0);
- missile->explode = 0;
- obj_free[ENEMYMISSILE][i] = 1;
- active_list[no_objects] = missile;
- no_objects++;
- num_active[ENEMYMISSILE]++;
- StartSound(0);
- return;
- }
- }
- }
-
- void MoveObjects(void)
- /* horrible sprawling routine... should be broken up */
- {
- register int i;
- register object *obj;
-
- for(i=0; i<no_objects; i++)
- {
- obj = active_list[i];
-
- if(obj->i_am_dying)
- continue;
- else
- obj->drawme = 1;
-
- switch(obj->type)
- {
- case FIXED:
- Rotate_Obj_Rel(obj, 2, 2, 2);
- break;
- case PLAYER:
- break;
- case ENEMYMISSILE:
- {
- register int i;
- register object *target;
-
- if(obj->timeinflight++>40)
- {
- obj->i_am_dying = 1;
- obj->explode = 1;
- break;
- }
-
- obj->trans_x += FastCos(obj->velocity, obj->heading);
- obj->trans_z -= FastSin(obj->velocity, obj->heading);
-
- if(obj->trans_x<0)
- obj->trans_x = MAX_WORLD_X;
- else if(obj->trans_x > MAX_WORLD_X)
- obj->trans_x = 0;
-
- if(obj->trans_z<0)
- obj->trans_z = MAX_WORLD_Z;
- else if(obj->trans_z>MAX_WORLD_Z)
- obj->trans_z = 0;
-
- /* check if missile hit something */
-
- for(i=0; i<no_objects; i++)
- {
- target = active_list[i];
-
- if(target->type==MYMISSILE)
- {
- register int temp, distance;
- temp = (target->trans_x + target->centre_x) -
- (obj->trans_x + obj->centre_x);
-
- distance = temp * temp;
-
- temp = (target->trans_y + target->centre_y) -
- (obj->trans_y + obj->centre_y);
-
- distance += temp * temp;
-
- temp = (target->trans_z + target->centre_z) -
- (obj->trans_z + obj->centre_z);
-
- distance += temp * temp;
-
- if(distance<(obj->radius + 2000))
- {
- obj->i_am_dying = target->i_am_dying = 1;
- obj->explode = target->explode = 1;
- StartSound(2);
- break;
- }
- }
- }
- Rotate_Obj_Rel(obj, 5, 0, 0);
- break;
- }
- case MYMISSILE:
- {
- register int i;
- register object *target;
-
- if(obj->timeinflight++>50)
- {
- obj->i_am_dying = 1;
- obj->explode = 1;
- break;
- }
-
- obj->trans_x += FastCos(obj->velocity, obj->heading);
- obj->trans_z -= FastSin(obj->velocity, obj->heading);
-
- if(obj->trans_x<0)
- obj->trans_x = MAX_WORLD_X;
- else if(obj->trans_x > MAX_WORLD_X)
- obj->trans_x = 0;
-
- if(obj->trans_z<0)
- obj->trans_z = MAX_WORLD_Z;
- else if(obj->trans_z>MAX_WORLD_Z)
- obj->trans_z = 0;
-
- /* check if missile hit something */
-
- for(i=0; i<no_objects; i++)
- {
- target = active_list[i];
-
- if(target->type<=MAMBA)
- {
- register int temp, distance;
- temp = (target->trans_x + target->centre_x) -
- (obj->trans_x + obj->centre_x);
-
- distance = temp * temp;
-
- temp = (target->trans_y + target->centre_y) -
- (obj->trans_y + obj->centre_y);
-
- distance += temp * temp;
-
- temp = (target->trans_z + target->centre_z) -
- (obj->trans_z + obj->centre_z);
-
- distance += temp * temp;
-
- if(distance<(obj->radius + 2000))
- {
- obj->i_am_dying = target->i_am_dying = 1;
- obj->explode = target->explode = 1;
-
- switch(target->type)
- {
- case FIXED: player_score += 1000; break;
- case THARGOID: player_score += 1500; break;
- case ENEMYMISSILE: player_score += 10; break;
- case KRAIT: player_score += 600; break;
- case MAMBA: player_score+= 1000;
- default: player_score += 300;
- }
-
- {
- register int temp = player_score>>12;
- if(temp>player_scale)
- {
- player_scale = temp;
- player_missiles++;
- }
- }
-
- StartSound(2);
- break;
- }
- }
- }
- Rotate_Obj_Rel(obj, 5, 0, 0);
- break;
- }
- case GUIDEDMISSILE:
- {
- register short dest, fdest, theight, height, s1, s2, i;
- register object *target;
-
- Rotate_Obj_Rel(obj, 5, 0, 0);
-
- if(obj->timeinflight++>100)
- {
- obj->i_am_dying = 1;
- obj->explode = 1;
- break;
- }
-
- if(obj->target==NULL) /* no target yet */
- {
- register int sh_dist = 0x7fffffff; /* a really big number */
-
- for(i=0; i<no_objects; i++)
- {
- if(active_list[i]->type<=MAMBA &&
- active_list[i]->type>ENEMYMISSILE)
- {
- register int temp, distance;
- register object *target = active_list[i];
-
- temp = (target->trans_x + target->centre_x) -
- (obj->trans_x + obj->centre_x);
-
- distance = temp * temp;
-
- temp = (target->trans_y + target->centre_y) -
- (obj->trans_y + obj->centre_y);
-
- distance += temp * temp;
-
- temp = (target->trans_z + target->centre_z) -
- (obj->trans_z + obj->centre_z);
-
- distance += temp * temp;
-
- if(distance<sh_dist)
- {
- obj->target = active_list[i];
- sh_dist = distance;
- }
- }
- }
- }
-
- target = (object *) obj->target;
-
- {
- register char flag = 0;
- for(i=0; i<no_objects; i++)
- {
- if(active_list[i]==target)
- {
- flag = 1;
- break;
- }
- }
- if(!flag)
- {
- obj->target = NULL; /* get a new target next frame */
- break;
- }
- }
-
- /* move missile */
-
- height = obj->trans_y + obj->centre_y;
-
- theight = target->trans_y + target->centre_y;
-
- if(theight>height && height<MAX_WORLD_Y-500)
- obj->trans_y += 5;
- else if(height>5)
- obj->trans_y -= 5;
-
- dest = GetTargetAngle(target, obj->trans_x+obj->centre_x,
- obj->trans_z+obj->centre_z);
-
- if(dest<0)
- break;
-
- s1 = dest - obj->heading; /* get +ve diff. heading */
- s2 = obj->heading + 360 - dest;
-
- fdest = abs(s1)>abs(s2) ? -s2 : s1;
-
- if(fdest>180)
- {
- DecreaseMissileVelocity(obj);
- }
- else
- {
- IncreaseMissileVelocity(obj);
- }
-
- if(fdest>0)
- {
- if(fdest>5)
- fdest = 5;
-
- Rotate_Obj_Rel(obj, 0, fdest, 0);
- obj->heading += fdest;
- }
- else
- {
- if(fdest<-5)
- {
- obj->heading -= 5;
- Rotate_Obj_Rel(obj, 0, -5, 0);
- }
- else
- {
- Rotate_Obj_Rel(obj, 0, fdest, 0);
- obj->heading += fdest;
- }
- }
-
- if(obj->heading>359)
- obj->heading -= 360;
- else if(obj->heading<0)
- obj->heading += 360;
-
- obj->trans_x += FastCos(obj->velocity, obj->heading);
- obj->trans_z -= FastSin(obj->velocity, obj->heading);
-
- if(obj->trans_x<0)
- obj->trans_x = MAX_WORLD_X;
- else if(obj->trans_x > MAX_WORLD_X)
- obj->trans_x = 0;
-
- if(obj->trans_z<0)
- obj->trans_z = MAX_WORLD_Z;
- else if(obj->trans_z>MAX_WORLD_Z)
- obj->trans_z = 0;
-
- /* now check if the target was hit! */
-
- {
- register int temp, distance;
-
- temp = (target->trans_x + target->centre_x) -
- (obj->trans_x + obj->centre_x);
-
- distance = temp * temp;
-
- temp = (target->trans_y + target->centre_y) -
- (obj->trans_y + obj->centre_y);
-
- distance += temp * temp;
-
- temp = (target->trans_z + target->centre_z) -
- (obj->trans_z + obj->centre_z);
-
- distance += temp * temp;
-
- if(distance<(obj->radius + 2500))
- {
- obj->i_am_dying = target->i_am_dying = 1;
- obj->explode = target->explode = 1;
-
- switch(target->type)
- {
- case FIXED: player_score += 1000; break;
- case THARGOID: player_score += 1500; break;
- case ENEMYMISSILE: player_score += 10; break;
- case KRAIT: player_score += 600; break;
- case MAMBA: player_score+= 1000;
- default: player_score += 300;
- }
-
- {
- register int temp = player_score>>12;
- if(temp>player_scale)
- {
- player_scale = temp;
- player_missiles++;
- }
- }
-
- StartSound(2);
- }
- }
- break;
- }
- case EXPLOSION: /* floats away */
- {
- int rad;
-
- if((--(obj->timeinflight))==0)
- {
- obj->i_am_dying = 1;
- obj->explode = 0;
- break;
- }
-
- rad = getrandom(0,10);
-
- if(obj->up_or_down)
- {
- if(obj->trans_y<MAX_WORLD_Y-100)
- obj->trans_y += rad;
- }
- else
- {
- if(obj->trans_y>100)
- obj->trans_y -= rad;
- }
-
- if(rad>5)
- rad = getrandom(1, 6);
- else
- rad = -getrandom(1, 6);
-
- Rotate_Obj_Rel(obj, rad+2, rad-1, rad+1);
-
- obj->trans_x += FastCos(obj->velocity, obj->heading);
- obj->trans_z -= FastSin(obj->velocity, obj->heading);
-
- if(obj->trans_x<0)
- obj->trans_x = MAX_WORLD_X;
- else if(obj->trans_x > MAX_WORLD_X)
- obj->trans_x = 0;
-
- if(obj->trans_z<0)
- obj->trans_z = MAX_WORLD_Z;
- else if(obj->trans_z>MAX_WORLD_Z)
- obj->trans_z = 0;
- break;
- }
- default: /* enemy ship combat algorithm... */
- {
- register short dest, fdest, height, s1, s2;
- int distance;
-
- if(obj->type==THARGOID)
- Rotate_Obj_Rel(obj, 0, 5, 0);
- else if(obj->type==KRAIT)
- Rotate_Obj_Rel(obj, 5, 0, 0);
-
- height = obj->trans_y + obj->centre_y;
-
- fdest = ey - height;
- fdest = abs(fdest);
-
- if(ey>height && height<MAX_WORLD_Y-500)
- {
- if(fdest>5)
- obj->trans_y += 5;
- else
- obj->trans_y += fdest;
- }
- else if(height>5)
- {
- if(fdest>5)
- obj->trans_y -= 5;
- else
- obj->trans_y -= fdest;
- }
-
- dest = GetPointAngle(&distance,obj->trans_x, obj->trans_z);
-
- if(dest<0)
- break;
-
- s1 = dest - obj->heading; /* get +ve diff. heading */
- s2 = obj->heading + 360 - dest;
-
- fdest = abs(s1)>abs(s2) ? -s2 : s1;
-
- if(fdest>180)
- {
- DecreaseVelocity(obj);
- }
- else
- {
- IncreaseVelocity(obj);
- }
-
- if(fdest>0)
- {
- if(fdest>5)
- fdest = 5;
-
- Rotate_Obj_Rel(obj, 0, fdest, 0);
- obj->heading += fdest;
- }
- else
- {
- if(fdest<-5)
- {
- obj->heading -= 5;
- Rotate_Obj_Rel(obj, 0, -5, 0);
- }
- else
- {
- Rotate_Obj_Rel(obj, 0, fdest, 0);
- obj->heading += fdest;
- }
- }
-
- if(abs(fdest)<10 && distance<(2500*2500))
- {
- if(obj->type==THARGOID)
- {
- if(getrandom(0, 20)==0)
- LaunchMissile(obj);
- }
- else if(obj->type==MAMBA)
- {
- if(getrandom(0,25)==0)
- LaunchMissile(obj);
- }
- else if(obj->type==KRAIT)
- {
- if(getrandom(0,35)==0)
- LaunchMissile(obj);
- }
- else
- {
- if(getrandom(0,45)==0)
- LaunchMissile(obj);
- }
- }
-
-
- if(obj->heading>359)
- obj->heading -= 360;
- else if(obj->heading<0)
- obj->heading += 360;
-
- obj->trans_x += FastCos(obj->velocity, obj->heading);
- obj->trans_z -= FastSin(obj->velocity, obj->heading);
-
- if(obj->trans_x<0)
- obj->trans_x = MAX_WORLD_X;
- else if(obj->trans_x > MAX_WORLD_X)
- obj->trans_x = 0;
-
- if(obj->trans_z<0)
- obj->trans_z = MAX_WORLD_Z;
- else if(obj->trans_z>MAX_WORLD_Z)
- obj->trans_z = 0;
-
- break;
- }
- }
- }
- }
-
- void UpdateObjects(void)
- /*
- Creates new objects, adding them to the game dynamically
- */
- {
- if(!num_active[FIXED]) /* space stations */
- {
- /* there are none left, so I'll create 4 new ones ... */
-
- AddNewObject(FIXED, 500, 1000, 500);
- AddNewObject(FIXED, MAX_WORLD_Z-500, 1000, 500);
- AddNewObject(FIXED, 500, 1000, MAX_WORLD_Z-500);
- AddNewObject(FIXED, MAX_WORLD_Z-500, 1000, MAX_WORLD_Z-500);
- }
-
- if(num_active[3]+num_active[4]+num_active[5]+num_active[6]+
- num_active[2]!=3)
- {
- switch(getrandom(0,3))
- {
- case 0:
- AddNewObject(getrandom(SHUTTLE,MAMBA), getrandom(600,7000), 1000, MAX_WORLD_Z-100);
- break;
- case 1:
- AddNewObject(getrandom(SHUTTLE,MAMBA), getrandom(600,7000), 1000, 100);
- break;
- case 2:
- AddNewObject(getrandom(SHUTTLE,MAMBA), MAX_WORLD_X-200, 1000, getrandom(600,7000));
- break;
- case 3:
- AddNewObject(getrandom(SHUTTLE,MAMBA), 100, 1000, getrandom(600,7000));
- break;
- }
- }
- }
-
- /* end of module enemy.c */
-