Add support for particles on crash-reset, use them in XR591 as example; on the way add support in the particle emitter for decaying emission rates, and use this feature for nitro fire instead of manually applying the decay
git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@9641 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
parent
2c677b46c0
commit
0dcb1fa792
31
data/gfx/sparks.xml
Normal file
31
data/gfx/sparks.xml
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<particles emitter="box" box_x="0.5" box_y="0.5" box_z="0.2">
|
||||||
|
|
||||||
|
<spreading angle="180" />
|
||||||
|
|
||||||
|
<velocity x="0.000"
|
||||||
|
y="0.004"
|
||||||
|
z="0.000" />
|
||||||
|
|
||||||
|
<material file="flaring-star.png" />
|
||||||
|
|
||||||
|
<!-- Amount of particles emitted per second -->
|
||||||
|
<rate min="200"
|
||||||
|
max="200"
|
||||||
|
decay_rate="200" />
|
||||||
|
|
||||||
|
<!-- Minimal and maximal lifetime of a particle, in milliseconds. -->
|
||||||
|
<lifetime min="500"
|
||||||
|
max="600" />
|
||||||
|
|
||||||
|
<!-- Size of the particles -->
|
||||||
|
<size min="0.1"
|
||||||
|
max="0.2" />
|
||||||
|
|
||||||
|
<color min="255 255 255"
|
||||||
|
max="255 255 255" />
|
||||||
|
|
||||||
|
<!-- How much time in milliseconds before the particle is fully faded out -->
|
||||||
|
<fadeout time="500" />
|
||||||
|
|
||||||
|
</particles>
|
@ -11,7 +11,8 @@
|
|||||||
|
|
||||||
<!-- Amount of particles emitted per second -->
|
<!-- Amount of particles emitted per second -->
|
||||||
<rate min="800"
|
<rate min="800"
|
||||||
max="1000" />
|
max="1000"
|
||||||
|
decay_rate="800" />
|
||||||
|
|
||||||
<!-- Minimal and maximal lifetime of a particle, in milliseconds. -->
|
<!-- Minimal and maximal lifetime of a particle, in milliseconds. -->
|
||||||
<lifetime min="100"
|
<lifetime min="100"
|
||||||
|
@ -98,6 +98,11 @@ Material::Material(const XMLNode *node, int index)
|
|||||||
|
|
||||||
node->get("mask", &m_mask);
|
node->get("mask", &m_mask);
|
||||||
|
|
||||||
|
if (m_crash_reset)
|
||||||
|
{
|
||||||
|
node->get("crash-reset-particles", &m_crash_reset_particles);
|
||||||
|
}
|
||||||
|
|
||||||
if (node->get("normal-map", &m_normal_map_tex))
|
if (node->get("normal-map", &m_normal_map_tex))
|
||||||
{
|
{
|
||||||
m_normal_map = true;
|
m_normal_map = true;
|
||||||
|
@ -80,6 +80,10 @@ private:
|
|||||||
bool m_drive_reset;
|
bool m_drive_reset;
|
||||||
/** If a kart is rescued when crashing into this surface. */
|
/** If a kart is rescued when crashing into this surface. */
|
||||||
bool m_crash_reset;
|
bool m_crash_reset;
|
||||||
|
|
||||||
|
/** Particles to show on crash-reset */
|
||||||
|
std::string m_crash_reset_particles;
|
||||||
|
|
||||||
/** If the property should be ignored in the physics. Example would be
|
/** If the property should be ignored in the physics. Example would be
|
||||||
* plants that a kart can just drive through. */
|
* plants that a kart can just drive through. */
|
||||||
bool m_ignore;
|
bool m_ignore;
|
||||||
@ -176,6 +180,9 @@ public:
|
|||||||
/** Returns if this material should trigger a rescue if a kart
|
/** Returns if this material should trigger a rescue if a kart
|
||||||
* crashes against it. */
|
* crashes against it. */
|
||||||
bool isCrashReset () const { return m_crash_reset; }
|
bool isCrashReset () const { return m_crash_reset; }
|
||||||
|
|
||||||
|
std::string getCrashResetParticles() const { return m_crash_reset_particles; }
|
||||||
|
|
||||||
bool highTireAdhesion () const { return m_high_tire_adhesion; }
|
bool highTireAdhesion () const { return m_high_tire_adhesion; }
|
||||||
const std::string&
|
const std::string&
|
||||||
getTexFname () const { return m_texname; }
|
getTexFname () const { return m_texname; }
|
||||||
|
@ -187,6 +187,8 @@ ParticleEmitter::ParticleEmitter(const ParticleKind* type,
|
|||||||
m_node = NULL;
|
m_node = NULL;
|
||||||
m_particle_type = NULL;
|
m_particle_type = NULL;
|
||||||
m_parent = parent;
|
m_parent = parent;
|
||||||
|
m_emission_decay_rate = 0;
|
||||||
|
|
||||||
setParticleType(type);
|
setParticleType(type);
|
||||||
assert(m_node != NULL);
|
assert(m_node != NULL);
|
||||||
|
|
||||||
@ -205,7 +207,8 @@ ParticleEmitter::~ParticleEmitter()
|
|||||||
} // ~ParticleEmitter
|
} // ~ParticleEmitter
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void ParticleEmitter::update()
|
|
||||||
|
void ParticleEmitter::update(float dt)
|
||||||
{
|
{
|
||||||
assert(m_magic_number == 0x58781325);
|
assert(m_magic_number == 0x58781325);
|
||||||
|
|
||||||
@ -222,6 +225,12 @@ void ParticleEmitter::update()
|
|||||||
transform.rotateVect(velocity);
|
transform.rotateVect(velocity);
|
||||||
m_emitter->setDirection(velocity);
|
m_emitter->setDirection(velocity);
|
||||||
|
|
||||||
|
if (m_emission_decay_rate > 0)
|
||||||
|
{
|
||||||
|
m_max_rate = m_min_rate = std::max(0.0f, (m_min_rate - m_emission_decay_rate*dt));
|
||||||
|
setCreationRate(m_min_rate);
|
||||||
|
}
|
||||||
|
|
||||||
// There seems to be no way to randomise the velocity for particles,
|
// There seems to be no way to randomise the velocity for particles,
|
||||||
// so we have to do this manually, by changing the default velocity.
|
// so we have to do this manually, by changing the default velocity.
|
||||||
// Irrlicht expects velocity (called 'direction') in m/ms!!
|
// Irrlicht expects velocity (called 'direction') in m/ms!!
|
||||||
@ -243,6 +252,9 @@ void ParticleEmitter::setCreationRate(float f)
|
|||||||
m_emitter->setMinParticlesPerSecond(int(f));
|
m_emitter->setMinParticlesPerSecond(int(f));
|
||||||
m_emitter->setMaxParticlesPerSecond(int(f));
|
m_emitter->setMaxParticlesPerSecond(int(f));
|
||||||
|
|
||||||
|
m_min_rate = f;
|
||||||
|
m_max_rate = f;
|
||||||
|
|
||||||
// FIXME: to work around irrlicht bug, when an emitter is paused by setting the rate
|
// FIXME: to work around irrlicht bug, when an emitter is paused by setting the rate
|
||||||
// to 0 results in a massive emission when enabling it back. In irrlicht 1.8
|
// to 0 results in a massive emission when enabling it back. In irrlicht 1.8
|
||||||
// the node has a method called "clearParticles" that should be cleaner than this
|
// the node has a method called "clearParticles" that should be cleaner than this
|
||||||
@ -280,32 +292,35 @@ void ParticleEmitter::setPosition(const Vec3 &pos)
|
|||||||
void ParticleEmitter::setParticleType(const ParticleKind* type)
|
void ParticleEmitter::setParticleType(const ParticleKind* type)
|
||||||
{
|
{
|
||||||
assert(m_magic_number == 0x58781325);
|
assert(m_magic_number == 0x58781325);
|
||||||
if (m_particle_type == type) return; // already the right type
|
bool isNewType = (m_particle_type != type);
|
||||||
|
if (isNewType)
|
||||||
if (m_node != NULL)
|
|
||||||
{
|
{
|
||||||
m_node->removeAll();
|
if (m_node != NULL)
|
||||||
m_node->removeAllAffectors();
|
{
|
||||||
}
|
m_node->removeAll();
|
||||||
else
|
m_node->removeAllAffectors();
|
||||||
{
|
}
|
||||||
m_node = irr_driver->addParticleNode();
|
else
|
||||||
|
{
|
||||||
|
m_node = irr_driver->addParticleNode();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_parent != NULL)
|
||||||
|
{
|
||||||
|
m_node->setParent(m_parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_particle_type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_parent != NULL)
|
m_emission_decay_rate = type->getEmissionDecayRate();
|
||||||
{
|
|
||||||
m_node->setParent(m_parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
m_particle_type = type;
|
|
||||||
|
|
||||||
Material* material = type->getMaterial();
|
Material* material = type->getMaterial();
|
||||||
const float minSize = type->getMinSize();
|
const float minSize = type->getMinSize();
|
||||||
const float maxSize = type->getMaxSize();
|
const float maxSize = type->getMaxSize();
|
||||||
const int lifeTimeMin = type->getMinLifetime();
|
const int lifeTimeMin = type->getMinLifetime();
|
||||||
const int lifeTimeMax = type->getMaxLifetime();
|
const int lifeTimeMax = type->getMaxLifetime();
|
||||||
|
|
||||||
assert(maxSize >= minSize);
|
assert(maxSize >= minSize);
|
||||||
assert(lifeTimeMax >= lifeTimeMin);
|
assert(lifeTimeMax >= lifeTimeMin);
|
||||||
|
|
||||||
@ -321,109 +336,124 @@ void ParticleEmitter::setParticleType(const ParticleKind* type)
|
|||||||
m_node->setName(debug_name.c_str());
|
m_node->setName(debug_name.c_str());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
m_min_rate = type->getMinRate();
|
||||||
|
m_max_rate = type->getMaxRate();
|
||||||
|
|
||||||
video::SMaterial& mat0 = m_node->getMaterial(0);
|
if (isNewType)
|
||||||
|
|
||||||
m_node->setPosition(m_position.toIrrVector());
|
|
||||||
|
|
||||||
if (material != NULL)
|
|
||||||
{
|
{
|
||||||
assert(material->getTexture() != NULL);
|
video::SMaterial& mat0 = m_node->getMaterial(0);
|
||||||
material->setMaterialProperties(&mat0);
|
|
||||||
m_node->setMaterialTexture(0, material->getTexture());
|
m_node->setPosition(m_position.toIrrVector());
|
||||||
|
|
||||||
mat0.ZWriteEnable = !material->isTransparent(); // disable z-buffer writes if material is transparent
|
if (material != NULL)
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_node->setMaterialTexture(0, irr_driver->getTexture((file_manager->getDataDir() + "/gui/main_help.png").c_str()));
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (type->getShape())
|
|
||||||
{
|
|
||||||
case EMITTER_POINT:
|
|
||||||
{
|
{
|
||||||
m_emitter = m_node->createPointEmitter(core::vector3df(m_particle_type->getVelocityX(),
|
assert(material->getTexture() != NULL);
|
||||||
m_particle_type->getVelocityY(),
|
material->setMaterialProperties(&mat0);
|
||||||
m_particle_type->getVelocityZ()), // velocity in m/ms
|
m_node->setMaterialTexture(0, material->getTexture());
|
||||||
type->getMinRate(), type->getMaxRate(),
|
|
||||||
type->getMinColor(), type->getMaxColor(),
|
mat0.ZWriteEnable = !material->isTransparent(); // disable z-buffer writes if material is transparent
|
||||||
lifeTimeMin, lifeTimeMax,
|
}
|
||||||
m_particle_type->getAngleSpread() /* angle */
|
else
|
||||||
);
|
{
|
||||||
break;
|
m_node->setMaterialTexture(0, irr_driver->getTexture((file_manager->getDataDir() + "/gui/main_help.png").c_str()));
|
||||||
}
|
}
|
||||||
|
|
||||||
case EMITTER_BOX:
|
|
||||||
|
switch (type->getShape())
|
||||||
{
|
{
|
||||||
const float box_size_x = type->getBoxSizeX()/2.0f;
|
case EMITTER_POINT:
|
||||||
const float box_size_y = type->getBoxSizeY()/2.0f;
|
|
||||||
|
|
||||||
m_emitter = m_node->createBoxEmitter(core::aabbox3df(-box_size_x, -box_size_y, -0.6f,
|
|
||||||
box_size_x, box_size_y, -0.6f - type->getBoxSizeZ()),
|
|
||||||
core::vector3df(m_particle_type->getVelocityX(),
|
|
||||||
m_particle_type->getVelocityY(),
|
|
||||||
m_particle_type->getVelocityZ()), // velocity in m/ms
|
|
||||||
type->getMinRate(), type->getMaxRate(),
|
|
||||||
type->getMinColor(), type->getMaxColor(),
|
|
||||||
lifeTimeMin, lifeTimeMax,
|
|
||||||
m_particle_type->getAngleSpread() /* angle */
|
|
||||||
);
|
|
||||||
|
|
||||||
#if VISUALIZE_BOX_EMITTER
|
|
||||||
if (m_parent != NULL)
|
|
||||||
{
|
{
|
||||||
for (int x=0; x<2; x++)
|
m_emitter = m_node->createPointEmitter(core::vector3df(m_particle_type->getVelocityX(),
|
||||||
|
m_particle_type->getVelocityY(),
|
||||||
|
m_particle_type->getVelocityZ()), // velocity in m/ms
|
||||||
|
type->getMinRate(), type->getMaxRate(),
|
||||||
|
type->getMinColor(), type->getMaxColor(),
|
||||||
|
lifeTimeMin, lifeTimeMax,
|
||||||
|
m_particle_type->getAngleSpread() /* angle */
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case EMITTER_BOX:
|
||||||
|
{
|
||||||
|
const float box_size_x = type->getBoxSizeX()/2.0f;
|
||||||
|
const float box_size_y = type->getBoxSizeY()/2.0f;
|
||||||
|
|
||||||
|
m_emitter = m_node->createBoxEmitter(core::aabbox3df(-box_size_x, -box_size_y, -0.6f,
|
||||||
|
box_size_x, box_size_y, -0.6f - type->getBoxSizeZ()),
|
||||||
|
core::vector3df(m_particle_type->getVelocityX(),
|
||||||
|
m_particle_type->getVelocityY(),
|
||||||
|
m_particle_type->getVelocityZ()), // velocity in m/ms
|
||||||
|
type->getMinRate(), type->getMaxRate(),
|
||||||
|
type->getMinColor(), type->getMaxColor(),
|
||||||
|
lifeTimeMin, lifeTimeMax,
|
||||||
|
m_particle_type->getAngleSpread() /* angle */
|
||||||
|
);
|
||||||
|
|
||||||
|
#if VISUALIZE_BOX_EMITTER
|
||||||
|
if (m_parent != NULL)
|
||||||
{
|
{
|
||||||
for (int y=0; y<2; y++)
|
for (int x=0; x<2; x++)
|
||||||
{
|
{
|
||||||
for (int z=0; z<2; z++)
|
for (int y=0; y<2; y++)
|
||||||
{
|
{
|
||||||
m_visualisation.push_back(
|
for (int z=0; z<2; z++)
|
||||||
irr_driver->getSceneManager()->addSphereSceneNode(0.05f, 16, m_parent, -1,
|
{
|
||||||
core::vector3df((x ? box_size_x : -box_size_x),
|
m_visualisation.push_back(
|
||||||
(y ? box_size_y : -box_size_y),
|
irr_driver->getSceneManager()->addSphereSceneNode(0.05f, 16, m_parent, -1,
|
||||||
-0.6 - (z ? 0 : type->getBoxSizeZ())))
|
core::vector3df((x ? box_size_x : -box_size_x),
|
||||||
);
|
(y ? box_size_y : -box_size_y),
|
||||||
|
-0.6 - (z ? 0 : type->getBoxSizeZ())))
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
fprintf(stderr, "[ParticleEmitter] Unknown shape\n");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
fprintf(stderr, "[ParticleEmitter] Unknown shape\n");
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_emitter->setMinParticlesPerSecond(int(m_min_rate));
|
||||||
|
m_emitter->setMaxParticlesPerSecond(int(m_max_rate));
|
||||||
|
}
|
||||||
|
|
||||||
m_emitter->setMinStartSize(core::dimension2df(minSize, minSize));
|
m_emitter->setMinStartSize(core::dimension2df(minSize, minSize));
|
||||||
m_emitter->setMaxStartSize(core::dimension2df(maxSize, maxSize));
|
m_emitter->setMaxStartSize(core::dimension2df(maxSize, maxSize));
|
||||||
m_node->setEmitter(m_emitter); // this grabs the emitter
|
|
||||||
m_emitter->drop(); // so we can drop our references
|
|
||||||
|
|
||||||
scene::IParticleFadeOutAffector *af = m_node->createFadeOutParticleAffector(video::SColor(0, 255, 255, 255),
|
if (isNewType)
|
||||||
type->getFadeoutTime());
|
|
||||||
m_node->addAffector(af);
|
|
||||||
af->drop();
|
|
||||||
|
|
||||||
if (type->getGravityStrength() != 0)
|
|
||||||
{
|
{
|
||||||
scene::IParticleGravityAffector *gaf = m_node->createGravityAffector(core::vector3df(00.0f, type->getGravityStrength(), 0.0f),
|
m_node->setEmitter(m_emitter); // this grabs the emitter
|
||||||
type->getForceLostToGravityTime());
|
m_emitter->drop(); // so we can drop our references
|
||||||
m_node->addAffector(gaf);
|
|
||||||
gaf->drop();
|
scene::IParticleFadeOutAffector *af = m_node->createFadeOutParticleAffector(video::SColor(0, 255, 255, 255),
|
||||||
}
|
type->getFadeoutTime());
|
||||||
|
m_node->addAffector(af);
|
||||||
const float fas = type->getFadeAwayStart();
|
af->drop();
|
||||||
const float fae = type->getFadeAwayEnd();
|
|
||||||
if (fas > 0.0f && fae > 0.0f)
|
if (type->getGravityStrength() != 0)
|
||||||
{
|
{
|
||||||
FadeAwayAffector* faa = new FadeAwayAffector(fas*fas, fae*fae);
|
scene::IParticleGravityAffector *gaf = m_node->createGravityAffector(core::vector3df(00.0f, type->getGravityStrength(), 0.0f),
|
||||||
m_node->addAffector(faa);
|
type->getForceLostToGravityTime());
|
||||||
faa->drop();
|
m_node->addAffector(gaf);
|
||||||
|
gaf->drop();
|
||||||
|
}
|
||||||
|
|
||||||
|
const float fas = type->getFadeAwayStart();
|
||||||
|
const float fae = type->getFadeAwayEnd();
|
||||||
|
if (fas > 0.0f && fae > 0.0f)
|
||||||
|
{
|
||||||
|
FadeAwayAffector* faa = new FadeAwayAffector(fas*fas, fae*fae);
|
||||||
|
m_node->addAffector(faa);
|
||||||
|
faa->drop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} // setParticleType
|
} // setParticleType
|
||||||
|
|
||||||
@ -436,6 +466,8 @@ void ParticleEmitter::addHeightMapAffector(Track* t)
|
|||||||
hmca->drop();
|
hmca->drop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
void ParticleEmitter::resizeBox(float size)
|
void ParticleEmitter::resizeBox(float size)
|
||||||
{
|
{
|
||||||
scene::IParticleBoxEmitter* emitter = (scene::IParticleBoxEmitter*)m_emitter;
|
scene::IParticleBoxEmitter* emitter = (scene::IParticleBoxEmitter*)m_emitter;
|
||||||
|
@ -66,13 +66,20 @@ private:
|
|||||||
|
|
||||||
unsigned int m_magic_number;
|
unsigned int m_magic_number;
|
||||||
|
|
||||||
|
/** Decay of emission rate, in particles per second */
|
||||||
|
int m_emission_decay_rate;
|
||||||
|
|
||||||
|
/** The irrlicht emitter contains this info, but as an int. We want it as a float */
|
||||||
|
float m_min_rate, m_max_rate;
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ParticleEmitter (const ParticleKind* type,
|
ParticleEmitter (const ParticleKind* type,
|
||||||
const Vec3 &position,
|
const Vec3 &position,
|
||||||
scene::ISceneNode* parent = NULL);
|
scene::ISceneNode* parent = NULL);
|
||||||
virtual ~ParticleEmitter();
|
virtual ~ParticleEmitter();
|
||||||
virtual void update ();
|
virtual void update (float dt);
|
||||||
void setCreationRate(float f);
|
void setCreationRate(float f);
|
||||||
int getCreationRate();
|
int getCreationRate();
|
||||||
|
|
||||||
|
@ -51,6 +51,7 @@ ParticleKind::ParticleKind(const std::string file) : m_min_start_color(255,255,2
|
|||||||
m_fade_away_start = -1.0f;
|
m_fade_away_start = -1.0f;
|
||||||
m_fade_away_end = -1.0f;
|
m_fade_away_end = -1.0f;
|
||||||
m_force_lost_to_gravity_time = 1000;
|
m_force_lost_to_gravity_time = 1000;
|
||||||
|
m_emission_decay_rate = 0;
|
||||||
|
|
||||||
|
|
||||||
// ----- Read XML file
|
// ----- Read XML file
|
||||||
@ -131,6 +132,7 @@ ParticleKind::ParticleKind(const std::string file) : m_min_start_color(255,255,2
|
|||||||
{
|
{
|
||||||
rate->get("min", &m_min_rate);
|
rate->get("min", &m_min_rate);
|
||||||
rate->get("max", &m_max_rate);
|
rate->get("max", &m_max_rate);
|
||||||
|
rate->get("decay_rate", &m_emission_decay_rate);
|
||||||
}
|
}
|
||||||
|
|
||||||
//std::cout << "m_min_rate = " << m_min_rate << "\n";
|
//std::cout << "m_min_rate = " << m_min_rate << "\n";
|
||||||
|
@ -81,6 +81,8 @@ private:
|
|||||||
/** Distance from camera at which particles start fading out, or negative if disabled */
|
/** Distance from camera at which particles start fading out, or negative if disabled */
|
||||||
float m_fade_away_start, m_fade_away_end;
|
float m_fade_away_start, m_fade_away_end;
|
||||||
|
|
||||||
|
int m_emission_decay_rate;
|
||||||
|
|
||||||
std::string m_name;
|
std::string m_name;
|
||||||
|
|
||||||
std::string m_material_file;
|
std::string m_material_file;
|
||||||
@ -137,6 +139,8 @@ public:
|
|||||||
void setBoxSizeY (float newVal) { m_box_y = newVal; }
|
void setBoxSizeY (float newVal) { m_box_y = newVal; }
|
||||||
void setBoxSizeZ (float newVal) { m_box_z = newVal; }
|
void setBoxSizeZ (float newVal) { m_box_z = newVal; }
|
||||||
|
|
||||||
|
int getEmissionDecayRate() const { return m_emission_decay_rate; }
|
||||||
|
|
||||||
std::string getName() const { return m_name; }
|
std::string getName() const { return m_name; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -104,6 +104,7 @@ Kart::Kart (const std::string& ident, Track* track, int position, bool is_first_
|
|||||||
m_nitro_kind = NULL;
|
m_nitro_kind = NULL;
|
||||||
m_zipper_fire = NULL;
|
m_zipper_fire = NULL;
|
||||||
m_zipper_fire_kind = NULL;
|
m_zipper_fire_kind = NULL;
|
||||||
|
m_collision_particles = NULL;
|
||||||
m_slipstream = NULL;
|
m_slipstream = NULL;
|
||||||
m_skidmarks = NULL;
|
m_skidmarks = NULL;
|
||||||
m_camera = NULL;
|
m_camera = NULL;
|
||||||
@ -390,6 +391,7 @@ Kart::~Kart()
|
|||||||
if(m_nitro) delete m_nitro;
|
if(m_nitro) delete m_nitro;
|
||||||
if(m_nitro_kind) delete m_nitro_kind;
|
if(m_nitro_kind) delete m_nitro_kind;
|
||||||
if(m_zipper_fire) delete m_zipper_fire;
|
if(m_zipper_fire) delete m_zipper_fire;
|
||||||
|
if(m_collision_particles) delete m_collision_particles;
|
||||||
if(m_zipper_fire_kind) delete m_zipper_fire_kind;
|
if(m_zipper_fire_kind) delete m_zipper_fire_kind;
|
||||||
if(m_slipstream) delete m_slipstream;
|
if(m_slipstream) delete m_slipstream;
|
||||||
if(m_rain) delete m_rain;
|
if(m_rain) delete m_rain;
|
||||||
@ -502,6 +504,7 @@ void Kart::reset()
|
|||||||
m_attachment->clear();
|
m_attachment->clear();
|
||||||
m_nitro->setCreationRate(0.0f);
|
m_nitro->setCreationRate(0.0f);
|
||||||
m_zipper_fire->setCreationRate(0.0f);
|
m_zipper_fire->setCreationRate(0.0f);
|
||||||
|
if (m_collision_particles) m_collision_particles->setCreationRate(0.0f);
|
||||||
m_powerup.reset();
|
m_powerup.reset();
|
||||||
|
|
||||||
m_race_position = m_initial_position;
|
m_race_position = m_initial_position;
|
||||||
@ -838,7 +841,7 @@ void Kart::update(float dt)
|
|||||||
//smoke drawing control point
|
//smoke drawing control point
|
||||||
if (UserConfigParams::m_graphical_effects)
|
if (UserConfigParams::m_graphical_effects)
|
||||||
{
|
{
|
||||||
if (m_terrain_particles) m_terrain_particles->update();
|
if (m_terrain_particles) m_terrain_particles->update(dt);
|
||||||
if (m_rain)
|
if (m_rain)
|
||||||
{
|
{
|
||||||
m_rain->setPosition( getCamera()->getCameraSceneNode()->getPosition() );
|
m_rain->setPosition( getCamera()->getCameraSceneNode()->getPosition() );
|
||||||
@ -846,8 +849,9 @@ void Kart::update(float dt)
|
|||||||
}
|
}
|
||||||
} // UserConfigParams::m_graphical_effects
|
} // UserConfigParams::m_graphical_effects
|
||||||
|
|
||||||
m_nitro->update();
|
m_nitro->update(dt);
|
||||||
m_zipper_fire->update();
|
m_zipper_fire->update(dt);
|
||||||
|
if (m_collision_particles) m_collision_particles->update(dt);
|
||||||
|
|
||||||
updatePhysics(dt);
|
updatePhysics(dt);
|
||||||
|
|
||||||
@ -1337,7 +1341,31 @@ void Kart::crashed(Kart *k, const Material *m)
|
|||||||
* for 0.5 seconds after a crash.
|
* for 0.5 seconds after a crash.
|
||||||
*/
|
*/
|
||||||
if(m && m->isCrashReset() && !playingEmergencyAnimation())
|
if(m && m->isCrashReset() && !playingEmergencyAnimation())
|
||||||
|
{
|
||||||
|
std::string particles = m->getCrashResetParticles();
|
||||||
|
if (particles.size() > 0)
|
||||||
|
{
|
||||||
|
ParticleKind* kind = ParticleKindManager::get()->getParticles(particles);
|
||||||
|
if (kind != NULL)
|
||||||
|
{
|
||||||
|
if (m_collision_particles == NULL)
|
||||||
|
{
|
||||||
|
Vec3 position(-getKartWidth()*0.35f, 0.06f, getKartLength()*0.5f);
|
||||||
|
m_collision_particles = new ParticleEmitter(kind, position, getNode());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_collision_particles->setParticleType(kind);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Unknown particles kind <%s> in material crash-reset properties\n", particles.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
forceRescue();
|
forceRescue();
|
||||||
|
}
|
||||||
if(World::getWorld()->getTime()-m_time_last_crash < 0.5f) return;
|
if(World::getWorld()->getTime()-m_time_last_crash < 0.5f) return;
|
||||||
|
|
||||||
m_time_last_crash = World::getWorld()->getTime();
|
m_time_last_crash = World::getWorld()->getTime();
|
||||||
@ -1942,11 +1970,8 @@ void Kart::updateGraphics(float dt, const Vec3& offset_xyz,
|
|||||||
|
|
||||||
if (m_zipper_fire)
|
if (m_zipper_fire)
|
||||||
{
|
{
|
||||||
// the std::max call is there to let fire fade out smoothly instead of stopping sharply
|
|
||||||
if (m_zipper_fire->getCreationRate() > 0)
|
if (m_zipper_fire->getCreationRate() > 0)
|
||||||
{
|
{
|
||||||
m_zipper_fire->setCreationRate(std::max(m_zipper_fire->getCreationRate() - dt*800.0f, 0.0f));
|
|
||||||
|
|
||||||
// the emitter box should spread from last frame's position to the current position
|
// the emitter box should spread from last frame's position to the current position
|
||||||
// if we want nitro to be emitted in a smooth, continuous flame and not in blobs
|
// if we want nitro to be emitted in a smooth, continuous flame and not in blobs
|
||||||
m_zipper_fire->resizeBox(std::max(0.25f, getSpeed()*dt));
|
m_zipper_fire->resizeBox(std::max(0.25f, getSpeed()*dt));
|
||||||
|
@ -163,6 +163,9 @@ private:
|
|||||||
/** The particle kind for the nitro. */
|
/** The particle kind for the nitro. */
|
||||||
ParticleKind *m_zipper_fire_kind;
|
ParticleKind *m_zipper_fire_kind;
|
||||||
|
|
||||||
|
/** For collisions */
|
||||||
|
ParticleEmitter *m_collision_particles;
|
||||||
|
|
||||||
/** Handles all slipstreaming. */
|
/** Handles all slipstreaming. */
|
||||||
SlipStream *m_slipstream;
|
SlipStream *m_slipstream;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user