/**\brief Update the Projectile * * Projectiles do all the normal Sprite things like moving. * Projectiles check for collisions with nearby Ships, and if they collide, * they deal damage to that ship. Note that since each projectile knows which ship fired it and will never collide with them. * * Projectiles have a life time limit (in milli-seconds). Each tick they need * to check if they've lived to long and need to disappear. * * Projectiles have the ability to track down a specific target. This only * means that they will turn slightly to head towards their target. */ void Projectile::Update( void ) { Sprite::Update(); // update momentum and other generic sprite attributes SpriteManager *sprites = SpriteManager::Instance(); // Check for projectile collisions Sprite* impact = sprites->GetNearestSprite( (Sprite*)this, 100,DRAW_ORDER_SHIP|DRAW_ORDER_PLAYER ); if( (impact != NULL) && (impact->GetID() != ownerID) && ((this->GetWorldPosition() - impact->GetWorldPosition()).GetMagnitude() < impact->GetRadarSize() )) { int damageDone=(weapon->GetPayload())*damageBoost; ((Ship*)impact)->Damage( damageDone ); if(impact->GetDrawOrder()==DRAW_ORDER_SHIP) ((AI*)impact)->AddEnemy(ownerID,damageDone); sprites->Delete( (Sprite*)this ); // Create a fire burst where this projectile hit the ship's shields. // TODO: This shows how much we need to improve our collision detection. Effect* hit = new Effect(this->GetWorldPosition(), "Resources/Animations/shield.ani", 0); hit->SetAngle( -this->GetAngle() ); hit->SetMomentum( impact->GetMomentum() ); sprites->Add( hit ); } // Expire the projectile after a time period if (( Timer::GetTicks() > secondsOfLife + start )) { sprites->Delete( (Sprite*)this ); } // Track the target Sprite* target = sprites->GetSpriteByID( targetID ); float tracking = weapon->GetTracking(); if( target != NULL && tracking > 0.00000001f ) { float angleTowards = normalizeAngle( ( target->GetWorldPosition() - this->GetWorldPosition() ).GetAngle() - GetAngle() ); SetMomentum( GetMomentum().RotateBy( angleTowards*tracking ) ); SetAngle( GetMomentum().GetAngle() ); } }
void Radar::Draw( SpriteManager &sprites ) { short int radar_mid_x = RADAR_MIDDLE_X + Video::GetWidth() - 129; short int radar_mid_y = RADAR_MIDDLE_Y + 5; int radarSize; const list<Sprite*>& spriteList = sprites.GetSprites(); for( list<Sprite*>::const_iterator iter = spriteList.begin(); iter != spriteList.end(); iter++) { Coordinate blip( -(RADAR_HEIGHT / 2.0), (RADAR_WIDTH / 2.0), (RADAR_HEIGHT / 2.0), -(RADAR_WIDTH / 2.0) ); Sprite *sprite = *iter; if( sprite->GetDrawOrder() == DRAW_ORDER_PLAYER ) continue; // Calculate the blip coordinate for this sprite Coordinate wpos = sprite->GetWorldPosition(); WorldToBlip( wpos, blip ); if( blip.ViolatesBoundary() == false ) { /* blip is on the radar */ /* Convert to screen coords */ blip.SetX( blip.GetX() + radar_mid_x ); blip.SetY( blip.GetY() + radar_mid_y ); radarSize = int((sprite->GetRadarSize() / float(visibility)) * (RADAR_HEIGHT/4.0)); Video::DrawCircle( blip, (radarSize>=1) ?radarSize: 1, 1, sprite->GetRadarColor() ); } } }
/**\brief The last function call to the ship before it get's deleted * * At this point, the ship still exists. It has not been removed from the Universe * * \note We don't want to make this a destructor call because we want the rest * of the system to still treat the ship normally. */ void AI::Killed( lua_State *L ) { LogMsg( WARN, "AI %s has been killed\n", GetName().c_str() ); SpriteManager *sprites = Simulation_Lua::GetSimulation(L)->GetSpriteManager(); Sprite* killer = sprites->GetSpriteByID( target ); if(killer != NULL) { if( killer->GetDrawOrder() == DRAW_ORDER_PLAYER ) { ((Player*)killer)->UpdateFavor( this->GetAlliance()->GetName(), -1 ); } } }
// Remove every sprite (planet, AI ship, projectile, effect, etc.) except the player's sprite void SpriteManager::DeleteAllExceptPlayer( void ) { list<Sprite *>::iterator i; for( i = spritelist->begin(); i != spritelist->end(); ++i ) { Sprite *s = (*i); if( s->GetDrawOrder() != DRAW_ORDER_PLAYER ) { DeleteSprite( s ); i = spritelist->begin(); // TODO: spritelist->remove() is called which ... makes this necessary? Right? } } }
// Removes all sprites matching type 'type' void SpriteManager::DeleteByType( int type ) { list<Sprite *>::iterator i; for( i = spritelist->begin(); i != spritelist->end(); ++i ) { Sprite *s = (*i); if( s->GetDrawOrder() == type ) { DeleteSprite( s ); i = spritelist->begin(); // TODO: spritelist->remove() is called which ... makes this necessary? Right? } } }
/**\brief Returns the number of non-player (AI) ships. */ int SpriteManager::GetAIShipCount( void ) { list<Sprite *>::iterator i; int count = 0; for( i = spritelist->begin(); i != spritelist->end(); ++i ) { Sprite *s = (*i); if(( s->GetDrawOrder() == DRAW_ORDER_SHIP ) && (s != player)) { count++; } } return count; }
xmlNodePtr Gate::ToXMLNode(string componentName) { char buff[256]; xmlNodePtr section = xmlNewNode(NULL, BAD_CAST componentName.c_str() ); xmlNewChild(section, NULL, BAD_CAST "name", BAD_CAST this->GetName().c_str() ); snprintf(buff, sizeof(buff), "%d", (int)this->GetWorldPosition().GetX() ); xmlNewChild(section, NULL, BAD_CAST "x", BAD_CAST buff ); snprintf(buff, sizeof(buff), "%d", (int)this->GetWorldPosition().GetY() ); xmlNewChild(section, NULL, BAD_CAST "y", BAD_CAST buff ); Sprite* exit = SpriteManager::Instance()->GetSpriteByID( exitID ); if( (exit != NULL) && (exit->GetDrawOrder() & (DRAW_ORDER_GATE_TOP|DRAW_ORDER_GATE_BOTTOM) ) ) { xmlNewChild(section, NULL, BAD_CAST "exit", BAD_CAST ((Gate*)exit)->GetName().c_str() ); } return section; }
/**\brief Get the min/max planet positions. Useful when generating traffic. * \note Returns the values through the pointer arguments. */ void SpriteManager::GetBoundaries(float *north, float *south, float *east, float *west) { *north = *south = *east = *west = 0; list<Sprite *>::iterator i; for( i = spritelist->begin(); i != spritelist->end(); ++i ) { Sprite *s = (*i); if( s->GetDrawOrder() == DRAW_ORDER_PLANET ) { Coordinate c = s->GetWorldPosition(); if(c.GetY() < *north) *north = c.GetY(); if(c.GetY() > *south) *south = c.GetY(); if(c.GetX() < *west) *west = c.GetX(); if(c.GetX() > *east) *east = c.GetX(); } } }
/**\brief Adds an enemy to the AI's list of enemies * \todo Remove the SpriteManager Instance access. */ void AI::AddEnemy(int spriteID, int damage){ //printf("Adding Enemy %d with damage %d\n",spriteID,damage); Sprite *spr = SpriteManager::Instance()->GetSpriteByID(spriteID); if(!spr){ this->RemoveEnemy(spriteID); return; } int drawOrder = spr->GetDrawOrder(); if( !(drawOrder==DRAW_ORDER_SHIP || drawOrder == DRAW_ORDER_PLAYER) ){ LogMsg(WARN, "Sprite ID %d is not a ship or player",spriteID); return; } // Don't forgive players that attack if( drawOrder == DRAW_ORDER_PLAYER ) { merciful = 0; } // printf("Adding Enemy %d with damage %d\n",spriteID,damage); enemy newE; newE.id=spriteID; newE.damage=damage; // Search the enemies list for this sprite, combine damage taken if found. list<enemy>::iterator it = lower_bound(enemies.begin() , enemies.end(), newE, AI::EnemyComp); if( (*it).id==spriteID ) (*it).damage += damage; else enemies.insert(it,newE); //printf("list of enemies:\n"); bool success=false; for(it=enemies.begin(); it!=enemies.end(); it++){ //printf("%d\n",it->id); if(it->id ==spriteID) success=true; } assert(success); //printf("Successfully Added Enemy %d with damage %d\n",spriteID,damage); }