Convert explosion from hardcoded particle system to our current XML system

git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@12964 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
auria
2013-06-24 18:40:30 +00:00
parent fb6c949911
commit 8c07a80162
6 changed files with 115 additions and 59 deletions

33
data/gfx/explosion.xml Normal file
View File

@@ -0,0 +1,33 @@
<?xml version="1.0"?>
<particles emitter="sphere" radius="0.3">
<spreading angle="180" />
<velocity x="0.000"
y="0.0035"
z="0.000" />
<material file="explode.png" />
<!-- Amount of particles emitted per second -->
<rate min="500"
max="800" />
<!-- Minimal and maximal lifetime of a particle, in milliseconds. -->
<lifetime min="1000"
max="1200" />
<!-- Size of the particles -->
<size min="0.65"
max="0.95"
x-increase-factor="0.6"
y-increase-factor="0.6"
/>
<color min="255 255 255"
max="255 255 255" />
<!-- How much time in milliseconds before the particle is fully faded out -->
<fadeout time="800" />
</particles>

View File

@@ -23,6 +23,8 @@
#include "graphics/irr_driver.hpp"
#include "graphics/material.hpp"
#include "graphics/material_manager.hpp"
#include "graphics/particle_emitter.hpp"
#include "graphics/particle_kind_manager.hpp"
#include "items/projectile_manager.hpp"
#include "race/race_manager.hpp"
#include "utils/vec3.hpp"
@@ -37,39 +39,10 @@ Explosion::Explosion(const Vec3& coord, const char* explosion_sound)
{
// short emision time, explosion, not constant flame
m_remaining_time = burst_time;
m_node = irr_driver->addParticleNode();
m_node->grab();
#ifdef DEBUG
m_node->setName("explosion");
#endif
m_node->setPosition(coord.toIrrVector());
Material* m = material_manager->getMaterial("explode.png");
m_node->setMaterialTexture(0, m->getTexture());
m->setMaterialProperties(&(m_node->getMaterial(0)), NULL);
m_node->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR );
scene::IParticleEmitter* em =
m_node->createSphereEmitter(core::vector3df(0.0f,0.0f,0.0f), 0.5f,
/* velocity in m/ms */core::vector3df(0.0f,0.005f,0.0f),
600, 900, // min max particles per sec
video::SColor(0, 0, 0, 0), // min colour
video::SColor(0, 0, 0, 0), // max colour
(int)((burst_time + explosion_time)
*1000.0f), // min life ms
(int)((burst_time + explosion_time)
*1000.0f), // max max life ms
90, // max angle
// min and max start size
core::dimension2df(0.3f, 0.3f),
core::dimension2df(0.75f, 0.75f)
);
m_node->setEmitter(em); // this grabs the emitter
em->drop(); // so we can drop it here without deleting it
scene::IParticleAffector* scale_affector =
m_node->createScaleParticleAffector(core::dimension2df(3.0f, 3.0f));
m_node->addAffector(scale_affector); // same goes for the affector
scale_affector->drop();
ParticleKindManager* pkm = ParticleKindManager::get();
ParticleKind* particles = pkm->getParticles("explosion.xml");
m_emitter = new ParticleEmitter(particles, coord, NULL);
} // Explosion
//-----------------------------------------------------------------------------
@@ -77,12 +50,9 @@ Explosion::Explosion(const Vec3& coord, const char* explosion_sound)
*/
Explosion::~Explosion()
{
if(m_node)
if(m_emitter)
{
m_node->drop();
// Remove from scene node by removing from parent.
irr_driver->removeNode(m_node);
m_node = NULL;
delete m_emitter;
}
} // ~Explosion
@@ -101,19 +71,20 @@ bool Explosion::updateAndDelete(float dt)
if (m_remaining_time < 0.0f && m_remaining_time >= -explosion_time)
{
scene::ISceneNode* node = m_emitter->getNode();
const int intensity = (int)(255-(m_remaining_time/-explosion_time)*255);
m_node->getMaterial(0).AmbientColor.setGreen(intensity);
m_node->getMaterial(0).DiffuseColor.setGreen(intensity);
m_node->getMaterial(0).EmissiveColor.setGreen(intensity);
node->getMaterial(0).AmbientColor.setGreen(intensity);
node->getMaterial(0).DiffuseColor.setGreen(intensity);
node->getMaterial(0).EmissiveColor.setGreen(intensity);
m_node->getMaterial(0).AmbientColor.setBlue(intensity);
m_node->getMaterial(0).DiffuseColor.setBlue(intensity);
m_node->getMaterial(0).EmissiveColor.setBlue(intensity);
node->getMaterial(0).AmbientColor.setBlue(intensity);
node->getMaterial(0).DiffuseColor.setBlue(intensity);
node->getMaterial(0).EmissiveColor.setBlue(intensity);
m_node->getMaterial(0).AmbientColor.setRed(intensity);
m_node->getMaterial(0).DiffuseColor.setRed(intensity);
m_node->getMaterial(0).EmissiveColor.setRed(intensity);
node->getMaterial(0).AmbientColor.setRed(intensity);
node->getMaterial(0).DiffuseColor.setRed(intensity);
node->getMaterial(0).EmissiveColor.setRed(intensity);
}
@@ -127,8 +98,8 @@ bool Explosion::updateAndDelete(float dt)
if (m_remaining_time > -explosion_time)
{
// Stop the emitter and wait a little while for all particles to have time to fade out
m_node->getEmitter()->setMinParticlesPerSecond(0);
m_node->getEmitter()->setMaxParticlesPerSecond(0);
m_emitter->getNode()->getEmitter()->setMinParticlesPerSecond(0);
m_emitter->getNode()->getEmitter()->setMaxParticlesPerSecond(0);
}
else
{

View File

@@ -30,6 +30,7 @@ using namespace irr;
class Vec3;
class SFXBase;
class ParticleEmitter;
const float explosion_time = 1.5f;
@@ -39,8 +40,8 @@ const float explosion_time = 1.5f;
class Explosion : public HitSFX
{
private:
float m_remaining_time;
scene::IParticleSystemSceneNode *m_node;
float m_remaining_time;
ParticleEmitter* m_emitter;
public:
Explosion(const Vec3& coord, const char* explosion_sound);

View File

@@ -381,14 +381,16 @@ void ParticleEmitter::setParticleType(const ParticleKind* type)
m_node->setMaterialTexture(0, irr_driver->getTexture((file_manager->getDataDir() + "gui/main_help.png").c_str()));
}
// velocity in m/ms
core::vector3df velocity(m_particle_type->getVelocityX(),
m_particle_type->getVelocityY(),
m_particle_type->getVelocityZ());
switch (type->getShape())
{
case EMITTER_POINT:
{
m_emitter = m_node->createPointEmitter(core::vector3df(m_particle_type->getVelocityX(),
m_particle_type->getVelocityY(),
m_particle_type->getVelocityZ()), // velocity in m/ms
m_emitter = m_node->createPointEmitter(velocity,
type->getMinRate(), type->getMaxRate(),
type->getMinColor(), type->getMaxColor(),
lifeTimeMin, lifeTimeMax,
@@ -404,13 +406,11 @@ void ParticleEmitter::setParticleType(const ParticleKind* type)
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
velocity,
type->getMinRate(), type->getMaxRate(),
type->getMinColor(), type->getMaxColor(),
lifeTimeMin, lifeTimeMax,
m_particle_type->getAngleSpread() /* angle */
m_particle_type->getAngleSpread()
);
#if VISUALIZE_BOX_EMITTER
@@ -435,6 +435,18 @@ void ParticleEmitter::setParticleType(const ParticleKind* type)
#endif
break;
}
case EMITTER_SPHERE:
{
m_emitter = m_node->createSphereEmitter(core::vector3df(0.0f,0.0f,0.0f) /* center */,
m_particle_type->getSphereRadius(),
velocity,
type->getMinRate(), type->getMaxRate(),
type->getMinColor(), type->getMaxColor(),
lifeTimeMin, lifeTimeMax,
m_particle_type->getAngleSpread()
);
break;
}
default:
{
fprintf(stderr, "[ParticleEmitter] Unknown shape\n");
@@ -476,6 +488,16 @@ void ParticleEmitter::setParticleType(const ParticleKind* type)
m_node->addAffector(faa);
faa->drop();
}
if (type->hasScaleAffector())
{
core::dimension2df factor = core::dimension2df(type->getScaleAffectorFactorX(),
type->getScaleAffectorFactorY());
scene::IParticleAffector* scale_affector =
m_node->createScaleParticleAffector(factor);
m_node->addAffector(scale_affector);
scale_affector->drop();
}
}
} // setParticleType

View File

@@ -42,6 +42,7 @@ ParticleKind::ParticleKind(const std::string file) : m_min_start_color(255,255,2
m_box_x = 0.5f;
m_box_y = 0.5f;
m_box_z = 0.5f;
m_sphere_radius = 0.5f;
m_angle_spread = 45;
m_velocity_x = 0.001f;
m_velocity_y = 0.001f;
@@ -51,6 +52,9 @@ ParticleKind::ParticleKind(const std::string file) : m_min_start_color(255,255,2
m_fade_away_end = -1.0f;
m_force_lost_to_gravity_time = 1000;
m_emission_decay_rate = 0;
m_has_scale_affector = NULL;
m_scale_affector_factor_x = 0.0f;
m_scale_affector_factor_y = 0.0f;
// ----- Read XML file
@@ -87,6 +91,12 @@ ParticleKind::ParticleKind(const std::string file) : m_min_start_color(255,255,2
xml->get("box_y", &m_box_y);
xml->get("box_z", &m_box_z);
}
else if (emitterShape == "sphere")
{
m_shape = EMITTER_SPHERE;
xml->get("radius", &m_sphere_radius);
}
else
{
fprintf(stderr, "[ParticleKind] <particles> main node has unknown value for attribute 'emitter'\n");
@@ -154,6 +164,10 @@ ParticleKind::ParticleKind(const std::string file) : m_min_start_color(255,255,2
size->get("min", &m_min_size);
size->get("max", &m_max_size);
}
bool has_x = size->get("x-increase-factor", &m_scale_affector_factor_x);
bool has_y = size->get("y-increase-factor", &m_scale_affector_factor_y);
m_has_scale_affector = (has_x || has_y);
//std::cout << "m_particle_size = " << m_particle_size << "\n";
//std::cout << "m_min_size = " << m_min_size << "\n";

View File

@@ -30,6 +30,7 @@ class Material;
enum EmitterShape
{
EMITTER_POINT,
EMITTER_SPHERE,
EMITTER_BOX
};
@@ -77,6 +78,9 @@ private:
/** For box emitters only */
float m_box_x, m_box_y, m_box_z;
/** For sphere emitters only */
float m_sphere_radius;
/** Distance from camera at which particles start fading out, or negative if disabled */
float m_fade_away_start, m_fade_away_end;
@@ -86,6 +90,10 @@ private:
std::string m_material_file;
bool m_has_scale_affector;
float m_scale_affector_factor_x;
float m_scale_affector_factor_y;
public:
/**
@@ -119,6 +127,8 @@ public:
float getBoxSizeY () const { return m_box_y; }
float getBoxSizeZ () const { return m_box_z; }
float getSphereRadius() const { return m_sphere_radius; }
int getAngleSpread () const { return m_angle_spread; }
float getVelocityX () const { return m_velocity_x; }
@@ -138,6 +148,11 @@ public:
int getEmissionDecayRate() const { return m_emission_decay_rate; }
bool hasScaleAffector() const { return m_has_scale_affector; }
float getScaleAffectorFactorX() const { return m_scale_affector_factor_x; }
float getScaleAffectorFactorY() const { return m_scale_affector_factor_y; };
std::string getName() const { return m_name; }
};