# Some fixes to projectiles
- Removed use of erase() in the middle of iterating through projectiles in CProjectileManager - that was dangerous! Replaced projectiles vector with a linked list to make it easy and efficient to delete elements in the middle. - Fixed animation. It seemed like a problem with updating the Y position came up and was more apparent as we lowered the turn length. This was SVN commit r5593.
This commit is contained in:
parent
0201229520
commit
7773b9b204
@ -410,10 +410,11 @@ void CGameView::EnumerateObjects(const CFrustum& frustum, SceneCollector* c)
|
||||
}
|
||||
}
|
||||
|
||||
const std::vector<CProjectile*>& projectiles = pProjectileMan.GetProjectiles();
|
||||
for (uint i = 0; i < projectiles.size(); ++i)
|
||||
const std::list<CProjectile*>& projectiles = pProjectileMan.GetProjectiles();
|
||||
std::list<CProjectile*>::const_iterator it = projectiles.begin();
|
||||
for (; it != projectiles.end(); ++it)
|
||||
{
|
||||
CModel* model = projectiles[i]->GetModel();
|
||||
CModel* model = (*it)->GetModel();
|
||||
|
||||
model->ValidatePosition();
|
||||
|
||||
@ -425,7 +426,7 @@ void CGameView::EnumerateObjects(const CFrustum& frustum, SceneCollector* c)
|
||||
&& losMgr->GetStatus(centre.X, centre.Z, g_Game->GetLocalPlayer()) & LOS_VISIBLE)
|
||||
{
|
||||
PROFILE( "submit projectiles" );
|
||||
c->SubmitRecursive(projectiles[i]->GetModel());
|
||||
c->SubmitRecursive((*it)->GetModel());
|
||||
}
|
||||
}
|
||||
PROFILE_END( "submit models" );
|
||||
|
@ -43,18 +43,12 @@ CProjectile::CProjectile( const CModel* Actor, const CVector3D& Position, const
|
||||
double t = s / m_Speed_H;
|
||||
// Required vertical velocity at launch:
|
||||
m_Speed_V = (float)( d_h / t + GRAVITY_2 * t );
|
||||
m_Speed_V_Previous = m_Speed_V;
|
||||
}
|
||||
|
||||
CProjectile::~CProjectile()
|
||||
{
|
||||
CProjectileManager& projectileManager = g_Game->GetWorld()->GetProjectileManager();
|
||||
std::vector<CProjectile*>::iterator it;
|
||||
for( it = projectileManager.m_Projectiles.begin(); it != projectileManager.m_Projectiles.end(); ++it )
|
||||
if( *it == this )
|
||||
{
|
||||
projectileManager.m_Projectiles.erase( it );
|
||||
break;
|
||||
}
|
||||
delete( m_Actor );
|
||||
}
|
||||
|
||||
@ -63,8 +57,8 @@ bool CProjectile::Update( size_t timestep_millis )
|
||||
m_Position_Previous = m_Position;
|
||||
m_Position.X += timestep_millis * m_Axis.x * m_Speed_H;
|
||||
m_Position.Z += timestep_millis * m_Axis.y * m_Speed_H;
|
||||
|
||||
m_Position.Y += (float)( timestep_millis * ( m_Speed_V - timestep_millis * GRAVITY_2 ) );
|
||||
m_Speed_V_Previous = m_Speed_V;
|
||||
m_Speed_V -= (float)( timestep_millis * GRAVITY );
|
||||
|
||||
float height = m_Position.Y - g_Game->GetWorld()->GetTerrain()->GetExactGroundLevel( m_Position.X, m_Position.Z );
|
||||
@ -100,8 +94,8 @@ void CProjectile::Interpolate( size_t timestep_millis )
|
||||
{
|
||||
m_Position_Graphics.X = m_Position_Previous.X + timestep_millis * m_Speed_H * m_Axis.x;
|
||||
m_Position_Graphics.Z = m_Position_Previous.Z + timestep_millis * m_Speed_H * m_Axis.y;
|
||||
m_Position_Graphics.Y = (float)( m_Position_Previous.Y + timestep_millis * ( m_Speed_V - timestep_millis * GRAVITY_2 ) );
|
||||
float dh_dt = (float)( m_Speed_V - timestep_millis * GRAVITY );
|
||||
m_Position_Graphics.Y = (float)( m_Position_Previous.Y + timestep_millis * ( m_Speed_V_Previous - timestep_millis * GRAVITY_2 ) );
|
||||
float dh_dt = (float)( m_Speed_V_Previous - timestep_millis * GRAVITY );
|
||||
float scale = 1 / sqrt( m_Speed_H * m_Speed_H + dh_dt * dh_dt );
|
||||
float scale2 = m_Speed_H * scale;
|
||||
|
||||
@ -248,8 +242,12 @@ CProjectileManager::~CProjectileManager()
|
||||
|
||||
void CProjectileManager::DeleteAll()
|
||||
{
|
||||
while( !( m_Projectiles.empty() ) )
|
||||
delete( m_Projectiles[0] ); // removes itself from m_Projectiles
|
||||
std::list<CProjectile*>::iterator it;
|
||||
for (it = m_Projectiles.begin(); it != m_Projectiles.end(); ++it)
|
||||
{
|
||||
delete *it;
|
||||
}
|
||||
m_Projectiles.clear();
|
||||
}
|
||||
|
||||
CProjectile* CProjectileManager::AddProjectile( const CModel* Actor, const CVector3D& Position, const CVector3D& Target, float Speed, CEntity* Originator, const CScriptObject& ImpactScript, const CScriptObject& MissScript )
|
||||
@ -261,23 +259,38 @@ CProjectile* CProjectileManager::AddProjectile( const CModel* Actor, const CVect
|
||||
|
||||
void CProjectileManager::DeleteProjectile( CProjectile* p )
|
||||
{
|
||||
delete( p );
|
||||
m_Projectiles.erase( std::find(m_Projectiles.begin(), m_Projectiles.end(), p) );
|
||||
delete p;
|
||||
}
|
||||
|
||||
void CProjectileManager::UpdateAll( size_t timestep )
|
||||
{
|
||||
m_LastTurnLength = timestep;
|
||||
for( size_t i = 0; i < m_Projectiles.size(); )
|
||||
if( !( m_Projectiles[i]->Update( timestep ) ) )
|
||||
delete( m_Projectiles[i] ); // removes itself from m_Projectiles
|
||||
|
||||
std::list<CProjectile*>::iterator it;
|
||||
for (it = m_Projectiles.begin(); it != m_Projectiles.end();)
|
||||
{
|
||||
CProjectile* p = *it;
|
||||
if (!p->Update(timestep))
|
||||
{
|
||||
// Projectile is dead due to having hit the ground or something
|
||||
std::list<CProjectile*>::iterator old = it;
|
||||
it++;
|
||||
m_Projectiles.erase(old);
|
||||
delete p;
|
||||
}
|
||||
else
|
||||
i++;
|
||||
{
|
||||
// Update completed successfully
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CProjectileManager::InterpolateAll( double relativeOffset )
|
||||
{
|
||||
size_t absoluteOffset = (size_t)( (double)m_LastTurnLength * relativeOffset );
|
||||
std::vector<CProjectile*>::iterator it;
|
||||
std::list<CProjectile*>::iterator it;
|
||||
for( it = m_Projectiles.begin(); it != m_Projectiles.end(); ++it )
|
||||
(*it)->Interpolate( absoluteOffset );
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ class CProjectile : public CJSObject<CProjectile>, public IEventTarget
|
||||
// Horizontal and vertical velocities
|
||||
float m_Speed_H;
|
||||
float m_Speed_V;
|
||||
float m_Speed_V_Previous;
|
||||
|
||||
CEntity* m_Originator;
|
||||
|
||||
@ -89,7 +90,7 @@ public:
|
||||
void UpdateAll( size_t timestep );
|
||||
void InterpolateAll( double frametime );
|
||||
|
||||
inline const std::vector<CProjectile*>& GetProjectiles() { return m_Projectiles; }
|
||||
inline const std::list<CProjectile*>& GetProjectiles() { return m_Projectiles; }
|
||||
|
||||
CProjectile* AddProjectile( const CModel* Actor, const CVector3D& Position, const CVector3D& Target, float Speed, CEntity* Originator, const CScriptObject& ImpactScript, const CScriptObject& MissScript );
|
||||
// Only if you have some reason to prematurely get rid of a projectile.
|
||||
@ -100,7 +101,7 @@ private:
|
||||
size_t m_LastTurnLength;
|
||||
|
||||
// Maintain a list of the projectiles in the world
|
||||
std::vector<CProjectile*> m_Projectiles;
|
||||
std::list<CProjectile*> m_Projectiles;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -144,3 +144,8 @@ void CSinglePlayerTurnManager::QueueLocalCommand(CNetMessage *pMsg)
|
||||
{
|
||||
QueueMessage(2, pMsg);
|
||||
}
|
||||
|
||||
bool CSinglePlayerTurnManager::NewTurnReady()
|
||||
{
|
||||
return true;
|
||||
}
|
@ -105,7 +105,7 @@ public:
|
||||
virtual void NewTurn() = 0;
|
||||
|
||||
// Used by CSimulation to ask whether it can call NewTurn.
|
||||
virtual bool NewTurnReady() { return true; }
|
||||
virtual bool NewTurnReady() = 0;
|
||||
|
||||
// Apply a function to all messages in a given batch.
|
||||
void IterateBatch(uint batch, BatchIteratorFunc *func, void *userdata);
|
||||
@ -121,6 +121,7 @@ public:
|
||||
|
||||
virtual void NewTurn();
|
||||
virtual void QueueLocalCommand(CNetMessage *pMsg);
|
||||
virtual bool NewTurnReady();
|
||||
};
|
||||
|
||||
extern CSinglePlayerTurnManager *g_SinglePlayerTurnManager;
|
||||
|
Loading…
Reference in New Issue
Block a user