void Span::GetBox(CBox2D &box) { box.Insert(m_p); box.Insert(m_v.m_p); if(this->m_v.m_type) { // arc, add quadrant points Point vs = m_p - m_v.m_c; Point ve = m_v.m_p - m_v.m_c; int qs = GetQuadrant(vs); int qe = GetQuadrant(ve); if(m_v.m_type == -1) { // swap qs and qe int t=qs; qs = qe; qe = t; } if(qe<qs)qe = qe + 4; double rad = m_v.m_p.dist(m_v.m_c); for(int i = qs; i<qe; i++) { box.Insert(m_v.m_c + QuadrantEndPoint(i) * rad); } } }
/**\brief SpriteManager update function. */ void SpriteManager::Update() { // Update the sprites inside each quadrant // TODO: Update only the sprites that are in nearby Quadrants list<Sprite *> all_oob; list<QuadTree*> nearby = GetQuadrantsNear( Camera::Instance()->GetFocusCoordinate(), QUADRANTSIZE*4 ); list<QuadTree*>::iterator iter; for ( iter = nearby.begin(); iter != nearby.end(); ++iter ) { (*iter)->Update(); list<Sprite *>* oob = (*iter)->FixOutOfBounds(); all_oob.splice(all_oob.end(), *oob ); delete oob; } // Move sprites to adjacent Quadrants as they cross boundaries list<Sprite *>::iterator i; for( i = all_oob.begin(); i != all_oob.end(); ++i ) { GetQuadrant( (*i)->GetWorldPosition() )->Insert( *i ); } //Delete all sprites queued to be deleted if (!spritesToDelete.empty()) { spritesToDelete.unique(); for( i = spritesToDelete.begin(); i != spritesToDelete.end(); ++i ) { DeleteSprite(*i); } spritesToDelete.clear(); } for ( iter = nearby.begin(); iter != nearby.end(); ++iter ) { (*iter)->ReBallance(); } DeleteEmptyQuadrants(); }
/* ----------------------------------------- CreateVector() get angle and distance travelled and calculate vector data points ----------------------------------------- */ void CreateVector(float fAngle, float fDistance, struct vector_t* pVectorN, struct vector_t* pVectorN_1) { /* coordinate system Y ^ | cartesian (-x,+y) | cartesian (+x,+y) polar (r, -t) | polar (r, -t) quad #3 | quad #4 -------------------o>>>>----------------> X cartesian (-x,-y) | cartesian (+x,-y) polar (r, +t) | polar (r, +t) quad #2 | quad #1 | (1) starting point assumes facing down the positive direction of 'X' axis (2) CW turn is '+', CCW turn in '-' */ float fOriginAngle1; float fOriginAngle2; // store distance traveled, direction-angle and the sum of directions pVectorN->fAngle = fAngle; pVectorN->fLength = fDistance; pVectorN->fAngleSum = pVectorN_1->fAngleSum - fAngle; // calculate cartesian coordinates pVectorN->fDx = pVectorN->fLength * cosf(pVectorN->fAngleSum); pVectorN->fDy = pVectorN->fLength * sinf(pVectorN->fAngleSum); pVectorN->fX = pVectorN_1->fX + pVectorN->fDx; pVectorN->fY = pVectorN_1->fY + pVectorN->fDy; // calculate polar coordinates if ( GetQuadrant(pVectorN) > 0 ) { pVectorN->fOriginLength = sqrt((pVectorN->fX * pVectorN->fX) + (pVectorN->fY * pVectorN->fY)); fOriginAngle1 = -1 * atan2f(pVectorN->fY, pVectorN->fX); fOriginAngle2 = -1 * atan2f(pVectorN->fY, pVectorN->fX); if ( fabsf(fOriginAngle1) < fabsf(fOriginAngle2) ) pVectorN->fOriginAngle = fOriginAngle1; else pVectorN->fOriginAngle = fOriginAngle2; } else { pVectorN->fOriginLength = 0; pVectorN->fOriginAngle = 0; } // calculate turn angle to realign facing start position pVectorN->fRealignAngle = fmodf(pVectorN->fAngleSum, __2PI__); }
/**\brief Deletes a sprite from the manager (Internal use). * \param sprite Pointer to the sprite * \details * This performs the actual deletion. */ bool SpriteManager::DeleteSprite( Sprite *sprite ) { spritelist->remove(sprite); spritelookup->erase( sprite->GetID() ); GetQuadrant( sprite->GetWorldPosition() )->Delete( sprite ); // Delete the sprite itself unless it is a Planet or Player. // Planets and Players are special sprites since they are Components and get saved. if( !(sprite->GetDrawOrder() & (DRAW_ORDER_PLAYER | DRAW_ORDER_PLANET | DRAW_ORDER_GATE_TOP | DRAW_ORDER_GATE_BOTTOM)) ) { delete sprite; } return true; }
/* ----------------------------------------- GetHomeCommand() calculate turn and distance command to get to 'home'/origin based on the location vector set ----------------------------------------- */ void GetHomeCommand(struct vector_t* pVector, float* pfTurn, float* pfDistance) { *pfDistance = pVector->fOriginLength; if ( GetQuadrant(pVector) > 0 ) { *pfTurn = pVector->fRealignAngle - __PI__ + pVector->fOriginAngle; *pfTurn = fmodf(*pfTurn, __2PI__); } else *pfTurn = pVector->fRealignAngle; }
/**\brief Deletes a sprite from the manager (Internal use). * \param sprite Pointer to the sprite * \details * This performs the actual deletion. */ bool SpriteManager::DeleteSprite( Sprite *sprite ) { spritelist->remove(sprite); spritelookup->erase( sprite->GetID() ); if( sprite==Camera::Instance()->GetFocus() ) { Camera::Instance()->Focus(NULL); } GetQuadrant( sprite->GetWorldPosition() )->Delete( sprite ); // Delete the sprite itself unless it is a Planet or Player. // Planets and Players are special sprites since they are Components and get saved. if( !(sprite->GetDrawOrder() & (DRAW_ORDER_PLAYER | DRAW_ORDER_PLANET)) ) { delete sprite; } return true; }
/**\brief Deletes a sprite from the manager (Internal use). * \param sprite Pointer to the sprite * \details * This performs the actual deletion. */ bool SpriteManager::DeleteSprite( Sprite *sprite ) { if(sprite == player) LogMsg(WARN, "Deleting player sprite. Should we be doing this?"); spritelist->remove( sprite ); spritelookup->erase( sprite->GetID() ); GetQuadrant( sprite->GetWorldPosition() )->Delete( sprite ); // Delete the sprite itself unless it is a Planet or Player. // Planets and Players are special sprites since they are Components and get saved. if( !(sprite->GetDrawOrder() & (DRAW_ORDER_PLAYER | DRAW_ORDER_PLANET )) ) { delete sprite; } return true; }
/**\brief Draws the current sprites */ void SpriteManager::Draw() { if( OPTION(int,"options/development/debug-quadtree") ) GetQuadrant( Camera::Instance()->GetFocusCoordinate() )->Draw( GetQuadrantCenter( Camera::Instance()->GetFocusCoordinate() ) ); list<Sprite *>::iterator i; list<Sprite*> *onscreen; float r = (Video::GetHalfHeight() < Video::GetHalfWidth() ? Video::GetHalfWidth() : Video::GetHalfHeight()) *V_SQRT2; onscreen = GetSpritesNear( Camera::Instance()->GetFocusCoordinate(), r, DRAW_ORDER_ALL); onscreen->sort(compareSpritePtrs); for( i = onscreen->begin(); i != onscreen->end(); ++i ) { (*i)->Draw(); } delete onscreen; }
/**\brief Draws the current sprites */ void SpriteManager::DrawQuadrantMap( Coordinate focus ) { GetQuadrant( focus )->Draw( GetQuadrantCenter( focus ) ); }
/**\brief SpriteManager update function. * \details Update the sprites inside each quadrant * \param lowFps If true, forces the wave-update method to be used rather than the full-update */ void SpriteManager::Update( lua_State *L, bool lowFps) { //this will contain every quadrant that we will potentially want to update list<QuadTree*> quadList; //if update-all is given then we update every quadrant //we do the same if tickCount == 0 even if update-all is not given // (in wave update mode, tickCount == 0 is when we want to update all quadrants) if( ! lowFps || tickCount == 0) { //need to get all of the quadrants in our map GetAllQuadrants(&quadList); } else { //wave update mode with tickCount != 0 -- update some quadrants Camera* camera = Simulation_Lua::GetSimulation(L)->GetCamera(); Coordinate currentPoint (camera->GetFocusCoordinate()); //always update centered on where we're at quadList.push_back (GetQuadrant (currentPoint)); //we ALWAYS update the current quadrant //we also ALWAYS update the 'regular' bands // the first band is at index 1 - index 0 would be the single quadrant in the middle // when we get the list of quadrants back we splice them onto the end of our overall list for (int i = 1; i <= numRegularBands; i ++) { list<QuadTree*> tempBandList = GetQuadrantsInBand (currentPoint, i); quadList.splice (quadList.end(), tempBandList); } //now - we SOMETIMES update the semi-regular bands // the ticks that each band is updated in is stored in the map // so we get our semiRegular update modulus of the ticks and then check the map // - the map has the tick index as the key and the band to update as the value int semiRegularTick = tickCount % semiRegularPeriod; map<int,int>::iterator findBand = ticksToBandNum.find (semiRegularTick); if (findBand != ticksToBandNum.end()) { //found the key //cout << "tick = " << tickCount << ", semiRegularTick = " << semiRegularTick << ", band = " << findBand->second << endl; list<QuadTree*> tempBandList = GetQuadrantsInBand (currentPoint, findBand->second); quadList.splice (quadList.end(), tempBandList); } else { //no semi-regular bands to update at this tick, do nothing } } // Find and Fix any Sprites that have moved out of bounds. list<Sprite *> all_oob; list<QuadTree*>::iterator iter; for ( iter = quadList.begin(); iter != quadList.end(); ++iter ) { (*iter)->Update(L); list<Sprite *>* oob = (*iter)->FixOutOfBounds(); all_oob.splice(all_oob.end(), *oob ); delete oob; } // Move sprites to adjacent Quadrants as they cross boundaries list<Sprite *>::iterator i; for( i = all_oob.begin(); i != all_oob.end(); ++i ) { GetQuadrant( (*i)->GetWorldPosition() )->Insert( *i ); } // Delete all sprites queued to be deleted if (!spritesToDelete.empty()) { spritesToDelete.sort(); // The list has to be sorted or unique doesn't work correctly. spritesToDelete.unique(); // Tell the AI that they've been killed for( i = spritesToDelete.begin(); i != spritesToDelete.end(); ++i ) { if( (*i)->GetDrawOrder() == DRAW_ORDER_SHIP ) { ((AI*)(*i))->Killed(L); } } for( i = spritesToDelete.begin(); i != spritesToDelete.end(); ++i ) { DeleteSprite(*i); } spritesToDelete.clear(); } for ( iter = quadList.begin(); iter != quadList.end(); ++iter ) { (*iter)->ReBallance(); } DeleteEmptyQuadrants(); // Update the tick count after all updates for this tick are done UpdateTickCount (); }
/**\brief Adds a sprite to the manager. * \param sprite Pointer to the sprite */ void SpriteManager::Add( Sprite *sprite ) { spritelist->push_back(sprite); spritelookup->insert(make_pair(sprite->GetID(),sprite)); GetQuadrant( sprite->GetWorldPosition() )->Insert( sprite ); }
/**\brief Draws the current sprites */ void SpriteManager::DrawQuadrantMap() { GetQuadrant( Camera::Instance()->GetFocusCoordinate() )->Draw( GetQuadrantCenter( Camera::Instance()->GetFocusCoordinate() ) ); }