Refactoring: flyable and hit effects now call

updateAndDelete instead of update. The return
value indicates if the flyable/hit effect needs
to be deleted. That removes callbacks to the
projectile manager to indicate that something
needs to be deleted.


git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@9619 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hikerstk 2011-08-25 00:06:33 +00:00
parent 8d8601655d
commit 771cf47339
15 changed files with 167 additions and 122 deletions

View File

@ -85,11 +85,11 @@ Explosion::~Explosion()
* \param dt Time step size. * \param dt Time step size.
* \return true If the explosion is finished. * \return true If the explosion is finished.
*/ */
bool Explosion::update(float dt) bool Explosion::updateAndDelete(float dt)
{ {
// The explosion sfx is shorter than the particle effect, // The explosion sfx is shorter than the particle effect,
// so no need to save the result of the update call. // so no need to save the result of the update call.
HitSFX::update(dt); HitSFX::updateAndDelete(dt);
m_remaining_time -= dt; m_remaining_time -= dt;
@ -133,4 +133,4 @@ bool Explosion::update(float dt)
} }
return false; // not finished return false; // not finished
} // update } // updateAndDelete

View File

@ -46,7 +46,7 @@ private:
public: public:
Explosion(const Vec3& coord, const char* explosion_sound); Explosion(const Vec3& coord, const char* explosion_sound);
~Explosion(); ~Explosion();
bool update (float delta_t); bool updateAndDelete(float delta_t);
bool hasEnded () { return m_remaining_time <= -explosion_time; } bool hasEnded () { return m_remaining_time <= -explosion_time; }
} ; } ;

View File

@ -44,7 +44,7 @@ public:
/** Updates a hit effect. Called once per frame. /** Updates a hit effect. Called once per frame.
* \param dt Time step size. * \param dt Time step size.
* \return True if the hit effect is finished and can be removed. */ * \return True if the hit effect is finished and can be removed. */
virtual bool update (float dt) = 0; virtual bool updateAndDelete(float dt) = 0;
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Sets that this SFX affects a player kart, which can be used to /** Sets that this SFX affects a player kart, which can be used to

View File

@ -61,11 +61,12 @@ void HitSFX::setPlayerKartHit()
} // setPlayerKartHit } // setPlayerKartHit
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** Updates the hit sfx, called one per time step. /** Updates the hit sfx, called one per time step. If this function returns
* true, the effect will be deleted.
* \param dt Time step size. * \param dt Time step size.
* \return true If the explosion is finished. * \return true If the explosion is finished.
*/ */
bool HitSFX::update(float dt) bool HitSFX::updateAndDelete(float dt)
{ {
return m_sfx->getStatus() != SFXManager::SFX_PLAYING; return m_sfx->getStatus() != SFXManager::SFX_PLAYING;
} // update } // updateAndDelete

View File

@ -36,7 +36,7 @@ private:
public: public:
HitSFX(const Vec3& coord, const char* explosion_sound); HitSFX(const Vec3& coord, const char* explosion_sound);
~HitSFX(); ~HitSFX();
virtual bool update (float dt); virtual bool updateAndDelete(float dt);
virtual void setPlayerKartHit(); virtual void setPlayerKartHit();
}; // HitSFX }; // HitSFX

View File

@ -90,9 +90,17 @@ void Bowling::init(const XMLNode &node, scene::IMesh *bowling)
} // init } // init
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
void Bowling::update(float dt) /** Updates the bowling ball ineach frame. If this function returns true, the
* object will be removed by the projectile manager.
* \param dt Time step size.
* \returns True of this object should be removed.
*/
bool Bowling::updateAndDelete(float dt)
{ {
Flyable::update(dt); bool can_be_deleted = Flyable::updateAndDelete(dt);
if(can_be_deleted)
return true;
const Kart *kart=0; const Kart *kart=0;
Vec3 direction; Vec3 direction;
float minDistance; float minDistance;
@ -121,7 +129,7 @@ void Bowling::update(float dt)
if(!material || material->isDriveReset()) if(!material || material->isDriveReset())
{ {
hit(NULL); hit(NULL);
return; return true;
} }
} }
btVector3 v = m_body->getLinearVelocity(); btVector3 v = m_body->getLinearVelocity();
@ -131,13 +139,17 @@ void Bowling::update(float dt)
if(vlen<0.8*m_speed*m_speed) if(vlen<0.8*m_speed*m_speed)
{ // bowling lost energy (less than 80%), i.e. it's too slow - speed it up: { // bowling lost energy (less than 80%), i.e. it's too slow - speed it up:
if(vlen==0.0f) { if(vlen==0.0f) {
v = btVector3(.5f, .0, 0.5f); // avoid 0 div. v = btVector3(.5f, .0, 0.5f); // avoid 0 div.
} }
m_body->setLinearVelocity(v*m_speed/sqrt(vlen)); m_body->setLinearVelocity(v*m_speed/sqrt(vlen));
} // vlen < 0.8*m_speed*m_speed } // vlen < 0.8*m_speed*m_speed
} // hat< m_max_height } // hat< m_max_height
if(vlen<0.1) if(vlen<0.1)
{
hit(NULL); hit(NULL);
} // update return true;
}
return false;
} // updateAndDelete
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------

View File

@ -43,7 +43,7 @@ private:
public: public:
Bowling(Kart* kart); Bowling(Kart* kart);
static void init(const XMLNode &node, scene::IMesh *bowling); static void init(const XMLNode &node, scene::IMesh *bowling);
virtual void update(float dt); virtual bool updateAndDelete(float dt);
const char* getExplosionSound() const { return "strike"; } const char* getExplosionSound() const { return "strike"; }

View File

@ -254,8 +254,8 @@ void Flyable::getClosestKart(const Kart **minKart, float *minDistSquared,
Vec3 *minDelta, const Kart* inFrontOf, Vec3 *minDelta, const Kart* inFrontOf,
const bool backwards) const const bool backwards) const
{ {
btTransform tProjectile = (inFrontOf != NULL ? inFrontOf->getTrans() btTransform trans_projectile = (inFrontOf != NULL ? inFrontOf->getTrans()
: getTrans()); : getTrans());
*minDistSquared = 999999.9f; *minDistSquared = 999999.9f;
*minKart = NULL; *minKart = NULL;
@ -271,9 +271,11 @@ void Flyable::getClosestKart(const Kart **minKart, float *minDistSquared,
kart->playingEmergencyAnimation() ) continue; kart->playingEmergencyAnimation() ) continue;
btTransform t=kart->getTrans(); btTransform t=kart->getTrans();
Vec3 delta = t.getOrigin()-tProjectile.getOrigin(); Vec3 delta = t.getOrigin()-trans_projectile.getOrigin();
// the Y distance is added again because karts above or below should not be prioritized when aiming // the Y distance is added again because karts above or below should//
float distance2 = delta.length2() + abs(t.getOrigin().getY() - tProjectile.getOrigin().getY())*2; // not be prioritized when aiming
float distance2 = delta.length2() + abs(t.getOrigin().getY()
- trans_projectile.getOrigin().getY())*2;
if(inFrontOf != NULL) if(inFrontOf != NULL)
{ {
@ -338,19 +340,25 @@ void Flyable::getLinearKartItemIntersection (const Vec3 &origin,
float gy = target_direction.getY(); float gy = target_direction.getY();
//Projected onto X-Z plane //Projected onto X-Z plane
float target_kart_speed = target_direction.length_2d() * target_kart->getSpeed(); float target_kart_speed = target_direction.length_2d()
* target_kart->getSpeed();
float target_kart_heading = target_kart->getHeading(); float target_kart_heading = target_kart->getHeading();
float dist = -(target_kart_speed / item_XZ_speed) * (dx * cosf(target_kart_heading) - float dist = -(target_kart_speed / item_XZ_speed)
dz * sinf(target_kart_heading)); * (dx * cosf(target_kart_heading) -
dz * sinf(target_kart_heading) );
float fire_th = (dx*dist - dz * sqrtf(dx*dx + dz*dz - dist*dist)) / (dx*dx + dz*dz); float fire_th = (dx*dist - dz * sqrtf(dx*dx + dz*dz - dist*dist))
fire_th = (((dist - dx*fire_th) / dz > 0) ? -acosf(fire_th): acosf(fire_th)); / (dx*dx + dz*dz);
fire_th = (((dist - dx*fire_th) / dz > 0) ? -acosf(fire_th)
: acosf(fire_th));
float time = 0.0f; float time = 0.0f;
float a = item_XZ_speed * sinf (fire_th) + target_kart_speed * sinf (target_kart_heading); float a = item_XZ_speed * sinf (fire_th)
float b = item_XZ_speed * cosf (fire_th) + target_kart_speed * cosf (target_kart_heading); + target_kart_speed * sinf (target_kart_heading);
float b = item_XZ_speed * cosf (fire_th)
+ target_kart_speed * cosf (target_kart_heading);
if (fabsf(a) > fabsf(b)) time = fabsf (dx / a); if (fabsf(a) > fabsf(b)) time = fabsf (dx / a);
else if (b != 0.0f) time = fabsf(dz / b); else if (b != 0.0f) time = fabsf(dz / b);
@ -364,16 +372,23 @@ void Flyable::getLinearKartItemIntersection (const Vec3 &origin,
time -= forw_offset / sqrt(a*a+b*b); time -= forw_offset / sqrt(a*a+b*b);
*fire_angle = fire_th; *fire_angle = fire_th;
*up_velocity = (0.5f * time * gravity) + (dy / time) + (gy * target_kart->getSpeed()); *up_velocity = (0.5f * time * gravity) + (dy / time)
+ (gy * target_kart->getSpeed());
} // getLinearKartItemIntersection } // getLinearKartItemIntersection
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void Flyable::update(float dt) /** Updates this flyable. It calls Moveable::update. If this function returns
* true, the flyable will be deleted by the projectile manager.
* \param dt Time step size.
* \returns True if this object can be deleted.
*/
bool Flyable::updateAndDelete(float dt)
{ {
m_time_since_thrown += dt; m_time_since_thrown += dt;
if(m_max_lifespan > -1 && m_time_since_thrown > m_max_lifespan) hit(NULL); if(m_max_lifespan > -1 && m_time_since_thrown > m_max_lifespan)
hit(NULL);
if(m_exploded) return; if(m_exploded) return true;
Vec3 xyz=getBody()->getWorldTransform().getOrigin(); Vec3 xyz=getBody()->getWorldTransform().getOrigin();
// Check if the flyable is outside of the track. If so, explode it. // Check if the flyable is outside of the track. If so, explode it.
@ -396,7 +411,7 @@ void Flyable::update(float dt)
xyz[0]>(*max)[0]-eps || xyz[2]>(*max)[2]-eps || xyz[1]>(*max)[1]-eps ) xyz[0]>(*max)[0]-eps || xyz[2]>(*max)[2]-eps || xyz[1]>(*max)[1]-eps )
{ {
hit(NULL); // flyable out of track boundary hit(NULL); // flyable out of track boundary
return; return true;
} }
// Add the position offset so that the flyable can adjust its position // Add the position offset so that the flyable can adjust its position
@ -404,6 +419,10 @@ void Flyable::update(float dt)
// problems finding the terrain in steep uphill sections). // problems finding the terrain in steep uphill sections).
TerrainInfo::update(xyz+m_position_offset); TerrainInfo::update(xyz+m_position_offset);
// Remove flyable if its
if(TerrainInfo::getMaterial()==NULL)
return true;
if(m_adjust_up_velocity) if(m_adjust_up_velocity)
{ {
float hat = xyz.getY()-getHoT(); float hat = xyz.getY()-getHoT();
@ -412,7 +431,8 @@ void Flyable::update(float dt)
// HAT is clamped by min/max height. This might be somewhat // HAT is clamped by min/max height. This might be somewhat
// unphysical, but feels right in the game. // unphysical, but feels right in the game.
float delta = m_average_height - std::max(std::min(hat, m_max_height), m_min_height); float delta = m_average_height - std::max(std::min(hat, m_max_height),
m_min_height);
Vec3 v = getVelocity(); Vec3 v = getVelocity();
assert(!isnan(v.getX())); assert(!isnan(v.getX()));
assert(!isnan(v.getX())); assert(!isnan(v.getX()));
@ -429,9 +449,11 @@ void Flyable::update(float dt)
} // if m_adjust_up_velocity } // if m_adjust_up_velocity
Moveable::update(dt); Moveable::update(dt);
} // update
// ----------------------------------------------------------------------------- return false;
} // updateAmdDelete
// ----------------------------------------------------------------------------
/** Updates the position of a projectile based on information received frmo the /** Updates the position of a projectile based on information received frmo the
* server. * server.
*/ */
@ -445,7 +467,7 @@ void Flyable::updateFromServer(const FlyableInfo &f, float dt)
Moveable::update(dt); Moveable::update(dt);
} // updateFromServer } // updateFromServer
// ----------------------------------------------------------------------------- // ----------------------------------------------------------------------------
/** Returns true if the item hit the kart who shot it (to avoid that an item /** Returns true if the item hit the kart who shot it (to avoid that an item
* that's too close to the shoter hits the shoter). * that's too close to the shoter hits the shoter).
* \param kart Kart who was hit. * \param kart Kart who was hit.
@ -457,8 +479,8 @@ bool Flyable::isOwnerImmunity(const Kart* kart_hit) const
m_time_since_thrown < 2.0f; m_time_since_thrown < 2.0f;
} // isOwnerImmunity } // isOwnerImmunity
// ----------------------------------------------------------------------------- // ----------------------------------------------------------------------------
/** Callback from the phycis in case that a kart or object is hit. /** Callback from the phycis in case that a kart or physical object is hit.
* kart The kart hit (NULL if no kart was hit). * kart The kart hit (NULL if no kart was hit).
* object The object that was hit (NULL if none). * object The object that was hit (NULL if none).
*/ */
@ -475,10 +497,11 @@ void Flyable::hit(Kart *kart_hit, PhysicalObject* object)
{ {
case PowerupManager::POWERUP_CAKE: case PowerupManager::POWERUP_CAKE:
{ {
hit_message += StringUtils::insertValues(getCakeString(), hit_message =
core::stringw(kart_hit->getName()), StringUtils::insertValues(getCakeString(),
core::stringw(m_owner->getName()) core::stringw(kart_hit->getName()),
).c_str(); core::stringw(m_owner->getName())
).c_str();
} }
break; break;
case PowerupManager::POWERUP_PLUNGER: case PowerupManager::POWERUP_PLUNGER:
@ -490,16 +513,18 @@ void Flyable::hit(Kart *kart_hit, PhysicalObject* object)
{ {
if (kart_hit == m_owner) if (kart_hit == m_owner)
{ {
hit_message += StringUtils::insertValues(getSelfBowlingString(), hit_message =
core::stringw(m_owner->getName()) StringUtils::insertValues(getSelfBowlingString(),
).c_str(); core::stringw(m_owner->getName())
).c_str();
} }
else else
{ {
hit_message += StringUtils::insertValues(getBowlingString(), hit_message =
core::stringw(kart_hit->getName()), StringUtils::insertValues(getBowlingString(),
core::stringw(m_owner->getName()) core::stringw(kart_hit->getName()),
).c_str(); core::stringw(m_owner->getName())
).c_str();
} }
} }
break; break;
@ -507,18 +532,29 @@ void Flyable::hit(Kart *kart_hit, PhysicalObject* object)
printf("Failed message for %i\n", m_type); printf("Failed message for %i\n", m_type);
assert(false); assert(false);
} }
gui->addMessage(translations->fribidize(hit_message), NULL, 3.0f, 40, video::SColor(255, 255, 255, 255), false); gui->addMessage(translations->fribidize(hit_message), NULL, 3.0f, 40,
video::SColor(255, 255, 255, 255), false);
} }
m_has_hit_something=true; m_has_hit_something=true;
// Notify the projectile manager that this rocket has hit something. // Notify the projectile manager that this rocket has hit something.
// The manager will create the appropriate explosion object. // The manager will create the appropriate explosion object.
projectile_manager->notifyRemove();
m_exploded=true; m_exploded=true;
if(!needsExplosion()) return; if(needsExplosion())
explode(kart_hit, object);
return;
} // hit
// ----------------------------------------------------------------------------
/** Creates the explosion physical effect, i.e. pushes the karts and ph
* appropriately. The corresponding visual/sfx needs to be added manually!
*/
void Flyable::explode(Kart *kart_hit, PhysicalObject *object)
{
// Apply explosion effect // Apply explosion effect
// ---------------------- // ----------------------
World *world = World::getWorld(); World *world = World::getWorld();

View File

@ -154,11 +154,12 @@ public:
virtual ~Flyable (); virtual ~Flyable ();
static void init (const XMLNode &node, scene::IMesh *model, static void init (const XMLNode &node, scene::IMesh *model,
PowerupManager::PowerupType type); PowerupManager::PowerupType type);
virtual void update (float); virtual bool updateAndDelete(float);
virtual HitEffect *getHitEffect() const;
void updateFromServer(const FlyableInfo &f, float dt); void updateFromServer(const FlyableInfo &f, float dt);
HitEffect *getHitEffect() const;
bool isOwnerImmunity(const Kart *kart_hit) const; bool isOwnerImmunity(const Kart *kart_hit) const;
virtual void hit (Kart* kart, PhysicalObject* obj=NULL);
void explode(Kart* kart, PhysicalObject* obj=NULL);
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** If true the up velocity of the flyable will be adjust so that the /** If true the up velocity of the flyable will be adjust so that the
* flyable stays at a height close to the average height. * flyable stays at a height close to the average height.
@ -173,11 +174,6 @@ public:
/** Called when this flyable hits the track. */ /** Called when this flyable hits the track. */
virtual void hitTrack () {}; virtual void hitTrack () {};
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Called when this flyable hit a kart or physical object.
* \param kart Pointer to the kart hit (NULL if no kart was hit).
* \param obj Pointer to the object hit (NULL if no object was hit). */
virtual void hit (Kart* kart, PhysicalObject* obj=NULL);
// ------------------------------------------------------------------------
/** Enables/disables adjusting ov velocity depending on height above /** Enables/disables adjusting ov velocity depending on height above
* terrain. Missiles can 'follow the terrain' with this adjustment, * terrain. Missiles can 'follow the terrain' with this adjustment,
* but gravity will basically be disabled. */ * but gravity will basically be disabled. */
@ -197,9 +193,8 @@ public:
/** Returns the sfx that should be played in case of an explosion. */ /** Returns the sfx that should be played in case of an explosion. */
virtual const char* getExplosionSound() const { return "explosion"; } virtual const char* getExplosionSound() const { return "explosion"; }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Indicates if an explosion needs to be added if this flyable /** Default is that each flyable needs an explosion effect. */
* is removed. */ virtual bool needsExplosion() const { return true; }
virtual bool needsExplosion() const {return true;}
}; // Flyable }; // Flyable
#endif #endif

View File

@ -118,21 +118,21 @@ Plunger::Plunger(Kart *kart) : Flyable(kart, PowerupManager::POWERUP_PLUNGER)
m_keep_alive = -1; m_keep_alive = -1;
} // Plunger } // Plunger
// ----------------------------------------------------------------------------- // ----------------------------------------------------------------------------
Plunger::~Plunger() Plunger::~Plunger()
{ {
if(m_rubber_band) if(m_rubber_band)
delete m_rubber_band; delete m_rubber_band;
} // ~Plunger } // ~Plunger
// ----------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void Plunger::init(const XMLNode &node, scene::IMesh *plunger_model) void Plunger::init(const XMLNode &node, scene::IMesh *plunger_model)
{ {
Flyable::init(node, plunger_model, PowerupManager::POWERUP_PLUNGER); Flyable::init(node, plunger_model, PowerupManager::POWERUP_PLUNGER);
} // init } // init
// ----------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void Plunger::update(float dt) bool Plunger::updateAndDelete(float dt)
{ {
// In keep-alive mode, just update the rubber band // In keep-alive mode, just update the rubber band
if(m_keep_alive >= 0) if(m_keep_alive >= 0)
@ -141,18 +141,19 @@ void Plunger::update(float dt)
if(m_keep_alive<=0) if(m_keep_alive<=0)
{ {
setHasHit(); setHasHit();
projectile_manager->notifyRemove(); return true;
} }
if(m_rubber_band != NULL) m_rubber_band->update(dt); if(m_rubber_band != NULL) m_rubber_band->update(dt);
return; return false;
} }
// Else: update the flyable and rubber band // Else: update the flyable and rubber band
Flyable::update(dt); bool ret = Flyable::updateAndDelete(dt);
if(m_rubber_band != NULL) m_rubber_band->update(dt); if(m_rubber_band != NULL) m_rubber_band->update(dt);
if(getHoT()==Track::NOHIT) return; return ret;
} // update
} // updateAndDelete
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
/** Virtual function called when the plunger hits something. /** Virtual function called when the plunger hits something.

View File

@ -47,16 +47,21 @@ public:
Plunger(Kart *kart); Plunger(Kart *kart);
~Plunger(); ~Plunger();
static void init(const XMLNode &node, scene::IMesh* missile); static void init(const XMLNode &node, scene::IMesh* missile);
virtual bool updateAndDelete(float dt);
virtual void hitTrack ();
virtual void hit (Kart *kart, PhysicalObject *obj=NULL);
// ------------------------------------------------------------------------
/** Sets the keep-alive value. Setting it to 0 will remove the plunger /** Sets the keep-alive value. Setting it to 0 will remove the plunger
* at the next update - which is used if the rubber band snaps. * at the next update - which is used if the rubber band snaps.
*/ */
void setKeepAlive(float t) {m_keep_alive = t;} void setKeepAlive(float t) {m_keep_alive = t;}
virtual void update (float dt); // ------------------------------------------------------------------------
virtual void hitTrack (); /** No hit effect when it ends. */
virtual void hit (Kart *kart, PhysicalObject *obj=NULL); virtual HitEffect *getHitEffect() const {return NULL; }
// ------------------------------------------------------------------------
/** A plunger does not explode if it is removed. */ /** Plunger does not need an explosion effect. */
virtual bool needsExplosion() const {return false;} virtual bool needsExplosion() const { return false; }
}; // Plunger }; // Plunger
#endif #endif

View File

@ -76,30 +76,11 @@ void ProjectileManager::update(float dt)
updateServer(dt); updateServer(dt);
} }
// Then check if any projectile hit something
if(m_something_was_hit)
{
Projectiles::iterator p = m_active_projectiles.begin();
while(p!=m_active_projectiles.end())
{
if(! (*p)->hasHit()) { p++; continue; }
if((*p)->needsExplosion())
{
HitEffect *he = (*p)->getHitEffect();
addHitEffect(he);
}
Flyable *f=*p;
Projectiles::iterator pNext=m_active_projectiles.erase(p); // returns the next element
delete f;
p=pNext;
} // while p!=m_active_projectiles.end()
}
HitEffects::iterator he = m_active_hit_effects.begin(); HitEffects::iterator he = m_active_hit_effects.begin();
while(he!=m_active_hit_effects.end()) while(he!=m_active_hit_effects.end())
{ {
// Update this hit effect. If it can be removed, remove it. // Update this hit effect. If it can be removed, remove it.
if((*he)->update(dt)) if((*he)->updateAndDelete(dt))
{ {
delete *he; delete *he;
HitEffects::iterator next = m_active_hit_effects.erase(he); HitEffects::iterator next = m_active_hit_effects.erase(he);
@ -119,19 +100,31 @@ void ProjectileManager::updateServer(float dt)
{ {
race_state->setNumFlyables(m_active_projectiles.size()); race_state->setNumFlyables(m_active_projectiles.size());
} }
for(Projectiles::iterator i = m_active_projectiles.begin();
i != m_active_projectiles.end(); ++i) Projectiles::iterator p = m_active_projectiles.begin();
while(p!=m_active_projectiles.end())
{ {
(*i)->update(dt); bool can_be_deleted = (*p)->updateAndDelete(dt);
// Store the state information on the server
if(network_manager->getMode()!=NetworkManager::NW_NONE) if(network_manager->getMode()!=NetworkManager::NW_NONE)
{ {
race_state->setFlyableInfo(i-m_active_projectiles.begin(), race_state->setFlyableInfo(p-m_active_projectiles.begin(),
FlyableInfo((*i)->getXYZ(), FlyableInfo((*p)->getXYZ(),
(*i)->getRotation(), (*p)->getRotation(),
(*i)->hasHit()) ); can_be_deleted) );
} }
} if(can_be_deleted)
{
HitEffect *he = (*p)->getHitEffect();
if(he)
addHitEffect(he);
Flyable *f=*p;
Projectiles::iterator p_next=m_active_projectiles.erase(p);
delete f;
p=p_next;
}
else
p++;
} // while p!=m_active_projectiles.end()
} // updateServer } // updateServer
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -140,7 +133,6 @@ void ProjectileManager::updateServer(float dt)
* (i.e. position, hit effects etc) */ * (i.e. position, hit effects etc) */
void ProjectileManager::updateClient(float dt) void ProjectileManager::updateClient(float dt)
{ {
m_something_was_hit = false;
unsigned int num_projectiles = race_state->getNumFlyables(); unsigned int num_projectiles = race_state->getNumFlyables();
if(num_projectiles != m_active_projectiles.size()) if(num_projectiles != m_active_projectiles.size())
fprintf(stderr, "Warning: num_projectiles %d active %d\n",num_projectiles, fprintf(stderr, "Warning: num_projectiles %d active %d\n",num_projectiles,
@ -154,7 +146,6 @@ void ProjectileManager::updateClient(float dt)
(*i)->updateFromServer(f, dt); (*i)->updateFromServer(f, dt);
if(f.m_exploded) if(f.m_exploded)
{ {
m_something_was_hit = true;
(*i)->hit(NULL); (*i)->hit(NULL);
} }
} // for i in m_active_projectiles } // for i in m_active_projectiles

View File

@ -53,14 +53,11 @@ private:
* being shown or have a sfx playing. */ * being shown or have a sfx playing. */
HitEffects m_active_hit_effects; HitEffects m_active_hit_effects;
bool m_something_was_hit;
void updateClient(float dt); void updateClient(float dt);
void updateServer(float dt); void updateServer(float dt);
public: public:
ProjectileManager() {m_something_was_hit=false;} ProjectileManager() {}
~ProjectileManager() {} ~ProjectileManager() {}
/** Notifies the projectile manager that something needs to be removed. */
void notifyRemove () {m_something_was_hit=true; }
void loadData (); void loadData ();
void cleanup (); void cleanup ();
void update (float dt); void update (float dt);

View File

@ -214,13 +214,15 @@ void RubberBall::init(const XMLNode &node, scene::IMesh *bowling)
Flyable::init(node, bowling, PowerupManager::POWERUP_RUBBERBALL); Flyable::init(node, bowling, PowerupManager::POWERUP_RUBBERBALL);
} // init } // init
// ----------------------------------------------------------------------------- // ----------------------------------------------------------------------------
/** Updates the rubber ball. /** Updates the rubber ball.
* \param dt Time step size. * \param dt Time step size.
* \returns True if the rubber ball should be removed.
*/ */
void RubberBall::update(float dt) bool RubberBall::updateAndDelete(float dt)
{ {
Flyable::update(dt); if(Flyable::updateAndDelete(dt))
return true;
// Update the target in case that the first kart was overtaken (or has // Update the target in case that the first kart was overtaken (or has
// finished the race). // finished the race).
@ -229,7 +231,7 @@ void RubberBall::update(float dt)
if(!m_target) // Remove this item from the game if(!m_target) // Remove this item from the game
{ {
hit(NULL); hit(NULL);
return; return true;
} }
checkDistanceToTarget(); checkDistanceToTarget();
@ -271,7 +273,9 @@ void RubberBall::update(float dt)
m_node->setScale(core::vector3df(1.0f, 1.0f, 1.0f)); m_node->setScale(core::vector3df(1.0f, 1.0f, 1.0f));
setXYZ(next_xyz); setXYZ(next_xyz);
} // update
return false;
} // updateAndDelete
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
/** Uses Hermite splines (Catmull-Rom) to interpolate the position of the /** Uses Hermite splines (Catmull-Rom) to interpolate the position of the
@ -430,7 +434,6 @@ void RubberBall::hit(Kart* kart, PhysicalObject* object)
{ {
// Else trigger the full explosion animation // Else trigger the full explosion animation
kart->handleExplosion(kart->getXYZ(), /*direct hit*/true); kart->handleExplosion(kart->getXYZ(), /*direct hit*/true);
projectile_manager->notifyRemove();
setHasHit(); setHasHit();
} }
return; return;

View File

@ -125,11 +125,15 @@ public:
RubberBall (Kart* kart); RubberBall (Kart* kart);
virtual ~RubberBall(); virtual ~RubberBall();
static void init(const XMLNode &node, scene::IMesh *bowling); static void init(const XMLNode &node, scene::IMesh *bowling);
virtual void update (float dt); virtual bool updateAndDelete(float dt);
virtual void hit (Kart* kart, PhysicalObject* obj=NULL); virtual void hit (Kart* kart, PhysicalObject* obj=NULL);
// ------------------------------------------------------------------------
/** This object does not create an explosion, all affects on /** This object does not create an explosion, all affects on
* karts are handled by this hit() function. */ * karts are handled by this hit() function. */
virtual bool needsExplosion() const {return false;} virtual HitEffect *getHitEffect() const {return NULL; }
// ------------------------------------------------------------------------
/** Plunger does not need an explosion effect. */
virtual bool needsExplosion() const { return false; }
}; // RubberBall }; // RubberBall