#include "WorldManager.h" #include "GameManager.h" void InitWorld(VWorld * world) { InitCamera(&world->Camera); InitPlayer(&world->Player); world->CurrentLevel = 0; LoadLevel(&world->Levels[world->CurrentLevel], "level", world); CopyLevel(&world->Levels[world->CurrentLevel], &world->Level); world->Camera.Position = world->Level.StartPos; world->Camera.Look = world->Camera.Position; switch (world->Level.Look) { case LEFT: world->Camera.Look.x -= 1.0; break; case RIGHT: world->Camera.Look.x += 1.0; break; case FORWARDS: world->Camera.Look.z -= 1.0; break; case BACKWARDS: default: world->Camera.Look.z += 1.0; break; } InitObject(&world->CrossHair); world->CrossHair.Position.x = 0.0; world->CrossHair.Position.y = 0.0; world->CrossHair.Position.z = -1.7; BuildCrossHairModel(&world->CrossHair.Model); InitObject(&world->Target); BuildTargetBoxModel(&world->Target.Model); world->Target.Billboard = true; world->Objects = world->Level.Objects; world->Level.Objects = NULL; InitPhysics(&world->Physics); FindTarget(world); world->Finished = false; } void InitPlayer(VPlayer * p) { p->NumRockets = INITIALROCKETS; p->Shields = INITIALSHIELDS; p->SpeedMultiplier = 1.0; } void AddWeapon(VWorld * world, int Type) { VWeapon * theWeapon; Vector front; VObjectWrapper * theWObject; if((Type == WEAPONTYPEROCKET && world->Player.NumRockets > 0) || Type == WEAPONTYPEBULLET) { if(Type == WEAPONTYPEROCKET) world->Player.NumRockets--; theWeapon = (VWeapon *) NewPtr(sizeof(VWeapon)); if (theWeapon != NULL) { InitWeapon(theWeapon, Type); AllocateWObject(&theWObject); theWObject->w = theWeapon; theWObject->Type = VWEAPON; theWObject->next = world->Objects; if (world->Objects != NULL) world->Objects->previous = theWObject; world->Objects = theWObject; ForwardsVector(&world->Camera, 1, &front); StartWeapon(theWeapon, &world->Camera.Position, ((front.x * world->Physics.Momentum.x) + (front.y * world->Physics.Momentum.y) + (front.z * world->Physics.Momentum.z)), &front, &world->Camera.Up); } } } void CleanUpWorld(VWorld * world) { VObjectWrapper * theWObject; CleanUpObject(&world->CrossHair); while(world->Objects != NULL) { theWObject = world->Objects; world->Objects = theWObject->next; CleanUpWObject(theWObject); DisposePtr((Ptr) theWObject); } CleanUpLevel(&world->Level); CleanUpLevel(&world->Levels[0]); } void DrawCrossHair(VWorld * world) { glPushMatrix(); glLoadIdentity(); glDisable(GL_DEPTH_TEST); DrawObject(&world->CrossHair); glEnable(GL_DEPTH_TEST); glPopMatrix(); } void DrawWorld(VWorld * world, float interval) { VObjectWrapper * theWObject; VObject * object; Vector front; /* Fill with semi transparent background */ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glDepthMask(GL_FALSE); glColor4f(0.0, 0.0, 0.0, ALPHAFILL / interval); glBegin(GL_QUADS); glVertex3f(-10.0, 10.0, -2.0); glVertex3f(10.0, 10.0, -2.0); glVertex3f(10.0, -10.0, -2.0); glVertex3f(-10.0, -10.0, -2.0); glEnd(); glDepthMask(GL_TRUE); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); ApplyCamera(&world->Camera); DrawLevel(&world->Level); for(theWObject = world->Objects; theWObject != NULL; theWObject = theWObject->next) { if(theWObject->target) { ForwardsVector(&world->Camera, 1, &front); WObjectObject(theWObject, &object); world->Target.Position.x = object->Position.x + (-front.x * object->Radius); world->Target.Position.y = object->Position.y + (-front.y * object->Radius); world->Target.Position.z = object->Position.z + (-front.z * object->Radius); glLineWidth(2); DrawObject(&world->Target); glLineWidth(1); } DrawWObject(theWObject); } DrawCrossHair(world); DrawConsole(&world->Console); } /* Radius is NOT squared */ Boolean InBounds(VWorld * world, Vector * Pos, float Radius) { #pragma unused (Radius) float RoomX, RoomY, RoomZ; RoomX = Pos->x / 40; RoomY = Pos->y / 40; RoomZ = Pos->z / 40; if((RoomX - (Radius / 40)) < 0 || (RoomX + (Radius / 40) - 1) > world->Levels[0].SizeX - 1 || (RoomY - (Radius / 40)) < 0 || (RoomY + (Radius / 40) - 1) > world->Levels[0].SizeY - 1 || (RoomZ - (Radius / 40)) < 0 || (RoomZ + (Radius / 40) - 1) > world->Levels[0].SizeZ - 1) return false; else { if(!world->Levels[0].Cells[((int)(RoomY + Radius/40) * (world->Levels[0].SizeX * world->Levels[0].SizeZ)) + ((int)RoomZ * world->Levels[0].SizeX) + (int)RoomX]) return false; if(!world->Levels[0].Cells[((int)(RoomY - Radius/40) * (world->Levels[0].SizeX * world->Levels[0].SizeZ)) + ((int)RoomZ * world->Levels[0].SizeX) + (int)RoomX]) return false; if(!world->Levels[0].Cells[((int)RoomY * (world->Levels[0].SizeX * world->Levels[0].SizeZ)) + ((int)(RoomZ + Radius/40) * world->Levels[0].SizeX) + (int)RoomX]) return false; if(!world->Levels[0].Cells[((int)RoomY * (world->Levels[0].SizeX * world->Levels[0].SizeZ)) + ((int)(RoomZ - Radius/40) * world->Levels[0].SizeX) + (int)RoomX]) return false; if(!world->Levels[0].Cells[((int)RoomY * (world->Levels[0].SizeX * world->Levels[0].SizeZ)) + ((int)RoomZ * world->Levels[0].SizeX) + (int)(RoomX + Radius/40)]) return false; if(!world->Levels[0].Cells[((int)RoomY * (world->Levels[0].SizeX * world->Levels[0].SizeZ)) + ((int)RoomZ * world->Levels[0].SizeX) + (int)(RoomX - Radius/40)]) return false; } return true; } static void IsGameOver(VWorld * w) { VObjectWrapper * theWObject; VObject * o; Boolean found; found = false; theWObject = w->Objects; while(theWObject != NULL) { WObjectObject(theWObject, &o); if(o) if(o->MustBeDestroyed && !(o->taggedForRemoval || theWObject->taggedForRemoval)) { found = true; break; } theWObject = theWObject->next; } if(!found) w->Finished = true; } void RunWorld(VWorld * world, float interval) { VObjectWrapper * theWObject; VObjectWrapper * obj; VObjectWrapper * next; VObjectWrapper * powerup; VObject * object; Vector front; Vector right; Boolean exploded; if((!InBounds(world, &world->Camera.Position, sqrt(PLAYERSHIPRADIUS))) && world->Player.Shields > 0) { DamagePlayer(world, world->Player.Shields); } powerup = NULL; theWObject = world->Objects; while(theWObject != NULL) { next = theWObject->next; if(theWObject == NULL) break; RunWObject(theWObject, interval, world); exploded = false; if(theWObject->exploded == 1) { AllocateWObject(&obj); AllocateExplosion(obj); WObjectObject(theWObject, &object); if (object != NULL && object->PowerupType != POWERUPTYPENONE) { AllocateWObject(&powerup); AllocatePowerup(powerup); InitPowerup(powerup->p); SetupPowerup(powerup->p, object->PowerupType, object->PowerupAmount); powerup->p->Object.Position = object->Position; } switch(theWObject->Type) { case VOBJECT: InitExplosion(obj->ex, theWObject->o, 7); CleanUpObject(theWObject->o); DisposePtr((Ptr)theWObject->o); break; case VENEMY: InitExplosion(obj->ex, &theWObject->e->Object, 7); CleanUpEnemy(theWObject->e); DisposePtr((Ptr)theWObject->e); break; case VWEAPON: InitExplosion(obj->ex, &theWObject->w->Object, theWObject->explosionLevel); CleanUpWeapon(theWObject->w); DisposePtr((Ptr)theWObject->w); break; } exploded = true; } if(theWObject->exploded == 2) { AllocateWObject(&obj); AllocateExplosion(obj); switch(theWObject->Type) { case VOBJECT: InitExplosion(obj->ex, theWObject->o, 1); break; case VENEMY: InitExplosion(obj->ex, &theWObject->e->Object, 1); break; } world->Objects->previous = obj; obj->next = world->Objects; world->Objects = obj; theWObject->exploded = 0; } if(theWObject->taggedForRemoval) { WObjectObject(theWObject, &object); if(object) if(object->MustBeDestroyed) IsGameOver(world); if(theWObject->target) FindTarget(world); if(theWObject->next) theWObject->next->previous = theWObject->previous; if(theWObject->previous) theWObject->previous->next = theWObject->next; else world->Objects = world->Objects->next; DisposePtr((Ptr)theWObject); } if(exploded) { if(world->Objects) world->Objects->previous = obj; obj->next = world->Objects; world->Objects = obj; if(powerup) { if(world->Objects) world->Objects->previous = powerup; powerup->next = world->Objects; world->Objects = powerup; } } theWObject = next; } ForwardsVector(&world->Camera, 1.0, &front); CrossProduct(&world->Camera.Up, &front, &right); RunPhysics(&world->Physics, &world->Camera.Position, &front, &right, &world->Camera.Up, interval); AddVector(&world->Camera.Position, &front, &world->Camera.Look); } void DamagePlayer(VWorld * world, int amount) { world->Player.Shields -= amount; if (world->Player.Shields <= 0) { InitCamera(&world->Camera); InitPhysics(&world->Physics); InitPlayer(&world->Player); world->Camera.Position = world->Level.StartPos; world->Camera.Look = world->Camera.Position; switch (world->Level.Look) { case LEFT: world->Camera.Look.x -= 1.0; break; case RIGHT: world->Camera.Look.x += 1.0; break; case FORWARDS: world->Camera.Look.z -= 1.0; break; case BACKWARDS: default: world->Camera.Look.z += 1.0; break; } } } void FindTarget(VWorld * w) { VObjectWrapper * theWObject; Boolean picked; theWObject = w->Objects; picked = false; while(theWObject != NULL) { if(theWObject->target) theWObject->target = false; if(!theWObject->picked && (theWObject->Type == VENEMY || theWObject->Type == VOBJECT) && !picked) { theWObject->picked = true; theWObject->target = true; picked = true; } theWObject = theWObject->next; } if(!picked) { theWObject = w->Objects; while(theWObject != NULL) { if(theWObject->picked) theWObject->picked = false; if((theWObject->Type == VENEMY || theWObject->Type == VOBJECT) && !picked) { theWObject->picked = true; theWObject->target = true; picked = true; } theWObject = theWObject->next; } } }