Fixed memory leak: the virtual createPhysics function of

GhostKart was not called, since it was called during when
the contrsuctor of Kart was executed (at this time the
GhostKart vtable wasn't set up, so Kart::createPhysics)
was called - which resulted in a memory leak since all
physics parts of the kart were actually allocated (just
not used). To fix this, karts are not constructed in two
phases: first a constructor, followed by a call to init
(during which virtual function can be used).
Fixed several bugs were physics data for a GhostKart
were accessed.


git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@10947 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hikerstk 2012-03-07 02:41:41 +00:00
parent 1e9b237b52
commit 72070db1a0
17 changed files with 184 additions and 171 deletions

View File

@ -186,7 +186,7 @@ void Attachment::clear()
// Resets the weight of the kart if the previous attachment affected it
// (e.g. anvil). This must be done *after* setting m_type to
// ATTACH_NOTHING in order to reset the physics parameters.
m_kart->updatedWeight();
m_kart->updateWeight();
} // clear
// -----------------------------------------------------------------------------
@ -285,7 +285,7 @@ void Attachment::hitBanana(Item *item, int new_attachment)
// Reduce speed once (see description above), all other changes are
// handled in Kart::updatePhysics
m_kart->adjustSpeed(stk_config->m_anvil_speed_factor);
m_kart->updatedWeight();
m_kart->updateWeight();
break ;
} // switch
}

View File

@ -315,7 +315,7 @@ void Powerup::use()
{
kart->getAttachment()->set(Attachment::ATTACH_ANVIL,
stk_config->m_anvil_time);
kart->updatedWeight();
kart->updateWeight();
kart->adjustSpeed(stk_config->m_anvil_speed_factor*0.5f);
// should we position the sound at the kart that is hit,

View File

@ -23,8 +23,7 @@
GhostKart::GhostKart(const std::string& ident)
: Kart(ident, /*world kart id*/99999,
/*position*/-1, /*is_first_kart*/false,
btTransform(), RaceManager::KT_GHOST)
/*position*/-1, btTransform())
{
m_current = 0;
} // GhostKart

View File

@ -49,7 +49,12 @@ public:
virtual void update (float dt);
virtual void addTransform(float time, const btTransform &trans);
virtual void reset();
// ------------------------------------------------------------------------
/** No physics body for ghost kart, so nothing to adjust. */
virtual void updateWeight() {};
// ------------------------------------------------------------------------
/** No physics for ghost kart. */
virtual void applyEngineForce (float force) {}
// ------------------------------------------------------------------------
// Not needed to create any physics for a ghost kart.
virtual void createPhysics() {}

View File

@ -73,8 +73,7 @@
* \param init_transform The initial position and rotation for this kart.
*/
Kart::Kart (const std::string& ident, unsigned int world_kart_id,
int position, bool is_first_kart,
const btTransform& init_transform, RaceManager::KartType type)
int position, const btTransform& init_transform)
: TerrainInfo(1),
Moveable(), EmergencyAnimation(this), MaxSpeed(this), m_powerup(this)
@ -93,6 +92,7 @@ Kart::Kart (const std::string& ident, unsigned int world_kart_id,
// kart_model is stored in the kart_properties all the time,
// there is no risk of a mesh being deleted to early.
m_kart_model = m_kart_properties->getKartModelCopy();
m_vehicle = NULL;
m_initial_position = position;
m_race_position = position;
m_world_kart_id = world_kart_id;
@ -147,6 +147,14 @@ Kart::Kart (const std::string& ident, unsigned int world_kart_id,
m_terrain_sound = NULL;
m_previous_terrain_sound = NULL;
} // Kart
// -----------------------------------------------------------------------------
/** This is a second initialisation phase, necessary since in the constructor
* virtual functions are not called for any superclasses.
*/
void Kart::init(RaceManager::KartType type, bool is_first_kart)
{
// In multiplayer mode, sounds are NOT positional
if (race_manager->getNumLocalPlayers() > 1)
{
@ -173,6 +181,7 @@ Kart::Kart (const std::string& ident, unsigned int world_kart_id,
fprintf(stdout, "Error: Could not allocate a sfx object for the kart. Further errors may ensue!\n");
}
bool animations = true;
const int anims = UserConfigParams::m_show_steering_animations;
if (anims == ANIMS_NONE)
@ -183,7 +192,6 @@ Kart::Kart (const std::string& ident, unsigned int world_kart_id,
{
animations = false;
}
loadData(type, is_first_kart, animations);
m_kart_gfx = new KartGFX(this);
@ -191,7 +199,121 @@ Kart::Kart (const std::string& ident, unsigned int world_kart_id,
m_kart_properties->getSkiddingProperties());
reset();
} // Kart
} // init
//-----------------------------------------------------------------------------
/** Reset before a new race. It will remove all attachments, and
* puts the kart back at its original start position.
*/
void Kart::reset()
{
if (m_flying)
{
m_flying = false;
stopFlying();
}
EmergencyAnimation::reset();
MaxSpeed::reset();
if (m_camera)
{
m_camera->reset();
m_camera->setInitialTransform();
}
// Reset animations and wheels
m_kart_model->reset();
// If the controller was replaced (e.g. replaced by end controller),
// restore the original controller.
if(m_saved_controller)
{
m_controller = m_saved_controller;
m_saved_controller = NULL;
}
m_kart_model->setAnimation(KartModel::AF_DEFAULT);
m_view_blocked_by_plunger = 0.0;
m_attachment->clear();
m_kart_gfx->reset();
m_skidding->reset();
if (m_collision_particles)
m_collision_particles->setCreationRateAbsolute(0.0f);
m_powerup.reset();
m_race_position = m_initial_position;
m_finished_race = false;
m_finish_time = 0.0f;
m_bubblegum_time = 0.0f;
m_invulnerable_time = 0.0f;
m_squash_time = 0.0f;
m_node->setScale(core::vector3df(1.0f, 1.0f, 1.0f));
m_collected_energy = 0;
m_has_started = false;
m_wheel_rotation = 0;
m_bounce_back_time = 0.0f;
m_time_last_crash = 0.0f;
m_speed = 0.0f;
m_view_blocked_by_plunger = 0.0f;
if(m_terrain_sound)
{
sfx_manager->deleteSFX(m_terrain_sound);
}
if(m_previous_terrain_sound)
{
sfx_manager->deleteSFX(m_previous_terrain_sound);
}
m_terrain_sound = NULL;
m_previous_terrain_sound = NULL;
if(m_engine_sound)
m_engine_sound->stop();
m_controls.m_steer = 0.0f;
m_controls.m_accel = 0.0f;
m_controls.m_brake = false;
m_controls.m_nitro = false;
m_controls.m_skid = false;
m_controls.m_fire = false;
m_controls.m_look_back = false;
m_slipstream->reset();
if(m_vehicle)
{
m_vehicle->reset();
}
setTrans(m_reset_transform);
applyEngineForce (0.0f);
Moveable::reset();
if (m_skidmarks)
{
m_skidmarks->reset();
const Track *track =
track_manager->getTrack( race_manager->getTrackName() );
m_skidmarks->adjustFog(track->isFogEnabled() );
}
TerrainInfo::update(getXYZ());
// Reset is also called when the kart is created, at which time
// m_controller is not yet defined, so this has to be tested here.
if(m_controller)
m_controller->reset();
// 3 strikes mode can hide the wheels
scene::ISceneNode** wheels = getKartModel()->getWheelNodes();
if(wheels[0]) wheels[0]->setVisible(true);
if(wheels[1]) wheels[1]->setVisible(true);
if(wheels[2]) wheels[2]->setVisible(true);
if(wheels[3]) wheels[3]->setVisible(true);
} // reset
// -----------------------------------------------------------------------------
/** Saves the old controller in m_saved_controller and stores a new
@ -446,10 +568,14 @@ Kart::~Kart()
if(m_skidmarks) delete m_skidmarks ;
World::getWorld()->getPhysics()->removeKart(this);
delete m_vehicle;
delete m_vehicle_raycaster;
delete m_uprightConstraint;
// Ghost karts don't have a body
if(m_body)
{
World::getWorld()->getPhysics()->removeKart(this);
delete m_vehicle;
delete m_vehicle_raycaster;
delete m_uprightConstraint;
}
for(int i=0; i<m_kart_chassis.getNumChildShapes(); i++)
{
@ -504,133 +630,14 @@ void Kart::capSpeed(float max_speed)
/** This method is to be called every time the mass of the kart is updated,
* which includes attaching an anvil to the kart (and detaching).
*/
void Kart::updatedWeight()
void Kart::updateWeight()
{
float mass = m_kart_properties->getMass() + m_attachment->weightAdjust();
btVector3 inertia;
m_kart_chassis.calculateLocalInertia(mass, inertia);
m_body->setMassProps(mass, inertia);
} // updatedWeight
//-----------------------------------------------------------------------------
/** Reset before a new race. It will remove all attachments, and
* puts the kart back at its original start position.
*/
void Kart::reset()
{
if (m_flying)
{
m_flying = false;
stopFlying();
}
EmergencyAnimation::reset();
MaxSpeed::reset();
if (m_camera)
{
m_camera->reset();
m_camera->setInitialTransform();
}
// Reset animations and wheels
m_kart_model->reset();
// If the controller was replaced (e.g. replaced by end controller),
// restore the original controller.
if(m_saved_controller)
{
m_controller = m_saved_controller;
m_saved_controller = NULL;
}
m_kart_model->setAnimation(KartModel::AF_DEFAULT);
m_view_blocked_by_plunger = 0.0;
m_attachment->clear();
m_kart_gfx->reset();
m_skidding->reset();
if (m_collision_particles)
m_collision_particles->setCreationRateAbsolute(0.0f);
m_powerup.reset();
m_race_position = m_initial_position;
m_finished_race = false;
m_finish_time = 0.0f;
m_bubblegum_time = 0.0f;
m_invulnerable_time = 0.0f;
m_squash_time = 0.0f;
m_node->setScale(core::vector3df(1.0f, 1.0f, 1.0f));
m_collected_energy = 0;
m_has_started = false;
m_wheel_rotation = 0;
m_bounce_back_time = 0.0f;
m_time_last_crash = 0.0f;
m_speed = 0.0f;
m_view_blocked_by_plunger = 0.0f;
if(m_terrain_sound)
{
sfx_manager->deleteSFX(m_terrain_sound);
}
if(m_previous_terrain_sound)
{
sfx_manager->deleteSFX(m_previous_terrain_sound);
}
m_terrain_sound = NULL;
m_previous_terrain_sound = NULL;
if(m_engine_sound)
m_engine_sound->stop();
m_controls.m_steer = 0.0f;
m_controls.m_accel = 0.0f;
m_controls.m_brake = false;
m_controls.m_nitro = false;
m_controls.m_skid = false;
m_controls.m_fire = false;
m_controls.m_look_back = false;
m_slipstream->reset();
m_vehicle->deactivateZipper();
// Set the brakes so that karts don't slide downhill
m_vehicle->setAllBrakes(5.0f);
setTrans(m_reset_transform);
applyEngineForce (0.0f);
Moveable::reset();
if (m_skidmarks)
{
m_skidmarks->reset();
const Track *track =
track_manager->getTrack( race_manager->getTrackName() );
m_skidmarks->adjustFog(track->isFogEnabled() );
}
m_vehicle->reset();
for(int j=0; j<m_vehicle->getNumWheels(); j++)
{
m_vehicle->updateWheelTransform(j, true);
}
TerrainInfo::update(getXYZ());
// Reset is also called when the kart is created, at which time
// m_controller is not yet defined, so this has to be tested here.
if(m_controller)
m_controller->reset();
// 3 strikes mode can hide the wheels
scene::ISceneNode** wheels = getKartModel()->getWheelNodes();
if(wheels[0]) wheels[0]->setVisible(true);
if(wheels[1]) wheels[1]->setVisible(true);
if(wheels[2]) wheels[2]->setVisible(true);
if(wheels[3]) wheels[3]->setVisible(true);
} // reset
} // updateWeight
//-----------------------------------------------------------------------------
/** Sets that this kart has finished the race and finishing time. It also
@ -1930,7 +1937,8 @@ void Kart::loadData(RaceManager::KartType type, bool is_first_kart,
// attachment is needed in createPhysics (which gets the mass, which
// is dependent on the attachment).
m_attachment = new Attachment(this);
createPhysics();
if(type!=RaceManager::KT_GHOST)
createPhysics();
// Attach Particle System

View File

@ -213,17 +213,18 @@ protected:
public:
Kart(const std::string& ident, unsigned int world_kart_id,
int position, bool is_first_kart,
const btTransform& init_transform, RaceManager::KartType type);
int position, const btTransform& init_transform);
virtual ~Kart();
virtual void init(RaceManager::KartType type, bool is_first_kart);
void loadData(RaceManager::KartType type, bool is_first_kart,
bool animatedModel);
virtual void updateGraphics(float dt, const Vec3& off_xyz,
const btQuaternion& off_rotation);
virtual void createPhysics ();
virtual void updateWeight ();
bool isInRest () const;
void setSuspensionLength();
void applyEngineForce (float force);
virtual void applyEngineForce (float force);
float handleNitro (float dt);
float getActualWheelForce();
@ -233,7 +234,6 @@ public:
void startEngineSFX ();
void adjustSpeed (float f);
void capSpeed (float max_speed);
void updatedWeight ();
virtual void collectedItem (Item *item, int random_attachment);
virtual void reset ();
void handleZipper (const Material *m=NULL, bool play_sound=false);

View File

@ -22,11 +22,9 @@
KartWithStats::KartWithStats(const std::string& ident,
unsigned int world_kart_id,
int position, bool is_first_kart,
const btTransform& init_transform,
RaceManager::KartType type)
: Kart(ident, world_kart_id, position, is_first_kart,
init_transform, type)
int position, const btTransform& init_transform)
: Kart(ident, world_kart_id, position,
init_transform)
{
reset();
} // KartWithStats

View File

@ -67,9 +67,8 @@ private:
public:
KartWithStats(const std::string& ident,
unsigned int world_kart_id,
int position, bool is_first_kart,
const btTransform& init_transform,
RaceManager::KartType type);
int position,
const btTransform& init_transform);
virtual void update(float dt);
virtual void reset();
virtual void handleExplosion(const Vec3& pos, bool direct_hit);

View File

@ -179,5 +179,6 @@ void Moveable::createBody(float mass, btTransform& trans,
void Moveable::setTrans(const btTransform &t)
{
m_transform=t;
m_motion_state->setWorldTransform(t);
if(m_motion_state)
m_motion_state->setWorldTransform(t);
} // setTrans

View File

@ -89,14 +89,16 @@ public:
void setXYZ(const Vec3& a)
{
m_transform.setOrigin(a);
m_motion_state->setWorldTransform(m_transform);
if(m_motion_state)
m_motion_state->setWorldTransform(m_transform);
}
// ------------------------------------------------------------------------
/** Sets the rotation of this moveable. */
void setRotation(const btQuaternion&a)
{
m_transform.setRotation(a);
m_motion_state->setWorldTransform(m_transform);
if(m_motion_state)
m_motion_state->setWorldTransform(m_transform);
}
// ------------------------------------------------------------------------
virtual void updateGraphics(float dt, const Vec3& off_xyz,

View File

@ -1108,6 +1108,7 @@ void cleanSuperTuxKart()
//delete in reverse order of what they were created in.
//see InitTuxkart()
Referee::cleanup();
if(ReplayPlay::get()) ReplayPlay::destroy();
if(race_manager) delete race_manager;
if(network_http) delete network_http;
if(news_manager) delete news_manager;

View File

@ -94,10 +94,8 @@ Kart *ProfileWorld::createKart(const std::string &kart_ident, int index,
Kart *new_kart = new KartWithStats(kart_ident,
/*world kart id*/ index,
/*position*/ index+1,
/*is_first_kart*/false,
init_pos,
RaceManager::KT_AI);
init_pos);
new_kart->init(RaceManager::KT_AI, /*is_first_kart*/false);
Controller *controller = loadAIController(new_kart);
new_kart->setController(controller);

View File

@ -197,9 +197,8 @@ Kart *World::createKart(const std::string &kart_ident, int index,
{
int position = index+1;
btTransform init_pos = m_track->getStartTransform(index);
Kart *new_kart = new Kart(kart_ident, index, position,
(local_player_id == 0), init_pos,
race_manager->getKartType(index));
Kart *new_kart = new Kart(kart_ident, index, position, init_pos);
new_kart->init(race_manager->getKartType(index), (local_player_id == 0));
Controller *controller = NULL;
switch(kart_type)
{

View File

@ -29,7 +29,7 @@ NetworkKart::NetworkKart(const std::string &kart_name,
int global_player_id,
RaceManager::KartType type)
: Kart(kart_name, world_kart_id, position,
/*is_first_kart*/false, init_transform, type)
init_transform)
{
m_global_player_id = global_player_id;
} // NetworkKart

View File

@ -109,7 +109,7 @@ void btKart::reset()
btWheelInfo &wheel = m_wheelInfo[i];
wheel.m_raycastInfo.m_suspensionLength = 0;
wheel.m_rotation = 0;
updateWheelTransformsWS(wheel);
updateWheelTransform(i, true);
}
m_zipper_active = false;
m_zipper_velocity = btScalar(0);
@ -121,6 +121,10 @@ void btKart::reset()
m_time_additional_impulse = 0;
m_additional_rotation = btVector3(0,0,0);
m_time_additional_rotation = 0;
// Set the brakes so that karts don't slide downhill
setAllBrakes(5.0f);
} // reset
// ----------------------------------------------------------------------------

View File

@ -59,9 +59,9 @@ void ReplayPlay::init()
void ReplayPlay::reset()
{
m_next = 0;
for(unsigned int i=0; i<m_ghost_karts.size(); i++)
for(unsigned int i=0; i<(unsigned int)m_ghost_karts.size(); i++)
{
m_ghost_karts[i]->reset();
m_ghost_karts[i].reset();
}
} // reset
@ -72,8 +72,8 @@ void ReplayPlay::reset()
void ReplayPlay::update(float dt)
{
// First update all ghost karts
for(unsigned int i=0; i<m_ghost_karts.size(); i++)
m_ghost_karts[i]->update(dt);
for(unsigned int i=0; i<(unsigned int)m_ghost_karts.size(); i++)
m_ghost_karts[i].update(dt);
} // update
@ -82,11 +82,7 @@ void ReplayPlay::update(float dt)
*/
void ReplayPlay::Load()
{
for(unsigned int i=0; i<m_ghost_karts.size(); i++)
{
delete m_ghost_karts[i];
}
m_ghost_karts.clear();
m_ghost_karts.clearAndDeleteAll();
char s[1024], s1[1024];
FILE *fd = openReplayFile(/*writeable*/false);
@ -184,6 +180,8 @@ void ReplayPlay::Load()
k, kart_id);
}
m_ghost_karts.push_back(new GhostKart(std::string(s1)));
m_ghost_karts[m_ghost_karts.size()-1].init(RaceManager::KT_GHOST,
/*is_first_kart*/false);
fgets(s, 1023, fd);
unsigned int size;
@ -211,7 +209,7 @@ void ReplayPlay::Load()
{
btQuaternion q(rx, ry, rz, rw);
btVector3 xyz(x, y, z);
m_ghost_karts[k]->addTransform(time, btTransform(q, xyz));
m_ghost_karts[k].addTransform(time, btTransform(q, xyz));
}
else
{

View File

@ -20,6 +20,7 @@
#define HEADER_REPLAY__PLAY_HPP
#include "replay/replay_base.hpp"
#include "utils/ptr_vector.hpp"
#include <string>
#include <vector>
@ -38,7 +39,7 @@ private:
unsigned int m_next;
/** All ghost karts. */
std::vector<GhostKart*> m_ghost_karts;
PtrVector<GhostKart> m_ghost_karts;
ReplayPlay();
~ReplayPlay();