diff --git a/data/nitro.xml b/data/nitro.xml
new file mode 100644
index 000000000..6a83923c2
--- /dev/null
+++ b/data/nitro.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/data/smoke.xml b/data/smoke.xml
new file mode 100644
index 000000000..8158f9c57
--- /dev/null
+++ b/data/smoke.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Makefile.am b/src/Makefile.am
index 27fbc8683..5f7f9368d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -73,6 +73,8 @@ supertuxkart_SOURCES = \
graphics/moving_texture.hpp \
graphics/particle_emitter.cpp \
graphics/particle_emitter.hpp \
+ graphics/particle_kind.cpp \
+ graphics/particle_kind.hpp \
graphics/shadow.cpp \
graphics/shadow.hpp \
graphics/skid_marks.cpp \
diff --git a/src/graphics/particle_emitter.cpp b/src/graphics/particle_emitter.cpp
index 3f73ee280..d6d37e441 100644
--- a/src/graphics/particle_emitter.cpp
+++ b/src/graphics/particle_emitter.cpp
@@ -21,18 +21,26 @@
#include "graphics/material.hpp"
#include "graphics/material_manager.hpp"
+#include "graphics/particle_kind.hpp"
#include "graphics/irr_driver.hpp"
#include "io/file_manager.hpp"
#include "utils/constants.hpp"
-ParticleEmitter::ParticleEmitter(float particleSize, core::vector3df position, Material* material,
- int minParticlesPerSecond, int maxParticlesPerSecond,
- video::SColor minStartColor, video::SColor maxStartColor,
- int lifeTimeMin, int lifeTimeMax, int maxAngle, int fadeOutTime,
- float directionMultiplier, float minSize, float maxSize, scene::ISceneNode* parent)
+ParticleEmitter::ParticleEmitter(ParticleKind* type, core::vector3df position,
+ scene::ISceneNode* parent)
{
- m_direction_multiplier = directionMultiplier;
m_node = irr_driver->addParticleNode();
+ m_particle_type = type;
+
+ Material* material = type->getMaterial();
+ const float minSize = type->getMinSize();
+ const float maxSize = type->getMaxSize();
+ const int lifeTimeMin = type->getMinLifetime();
+ const int lifeTimeMax = type->getMaxLifetime();
+
+ assert(material->getTexture() != NULL);
+ assert(maxSize >= minSize);
+ assert(lifeTimeMax >= lifeTimeMin);
#ifdef DEBUG
std::string debug_name = std::string("particles(") + material->getTexture()->getName().getPath().c_str() + ")";
@@ -53,20 +61,22 @@ ParticleEmitter::ParticleEmitter(float particleSize, core::vector3df position, M
m_node->setMaterialTexture(0, material->getTexture());
// FIXME: does the maxAngle param work at all??
-
- m_emitter = m_node->createPointEmitter(core::vector3df(0.0f, 0.3f, 0.0f), // velocity in m/ms
- minParticlesPerSecond, maxParticlesPerSecond,
- minStartColor, maxStartColor,
+ // FIXME: the min and max color params don't appear to work
+ m_emitter = m_node->createPointEmitter(core::vector3df(0.0f, 0.0f, 0.0f), // velocity in m/ms
+ type->getMinRate(), type->getMaxRate(),
+ type->getMinColor(), type->getMaxColor(),
lifeTimeMin, lifeTimeMax,
- maxAngle
+ 0 /* angle */
);
m_emitter->setMinStartSize(core::dimension2df(minSize, minSize));
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
- // FIXME: fade-out color doesn't seem to quite work
- scene::IParticleFadeOutAffector *af = m_node->createFadeOutParticleAffector(video::SColor(0, 255, 0, 0), fadeOutTime);
+ // FIXME: this is ridiculous, the fadeout time should be equal to the lifetime, except that the
+ // lifetime is random...
+ scene::IParticleFadeOutAffector *af = m_node->createFadeOutParticleAffector(video::SColor(0, 0, 0, 0),
+ type->getFadeoutTime());
m_node->addAffector(af);
af->drop();
@@ -86,12 +96,14 @@ void ParticleEmitter::update()
// No particles to emit, no need to change the speed
if (m_emitter->getMinParticlesPerSecond() == 0) return;
+ const float spreading = m_particle_type->getSpreadFactor();
+
// There seems to be no way to randomise the velocity for particles,
// so we have to do this manually, by changing the default velocity.
// Irrlicht expects velocity (called 'direction') in m/ms!!
- Vec3 dir(cos(DEGREE_TO_RAD*(rand()%180))*m_direction_multiplier,
- sin(DEGREE_TO_RAD*(rand()%100))*m_direction_multiplier,
- sin(DEGREE_TO_RAD*(rand()%180))*m_direction_multiplier);
+ Vec3 dir(cos(DEGREE_TO_RAD*(rand()%180))*spreading,
+ sin(DEGREE_TO_RAD*(rand()%100))*spreading,
+ sin(DEGREE_TO_RAD*(rand()%180))*spreading);
m_emitter->setDirection(dir.toIrrVector());
} // update
diff --git a/src/graphics/particle_emitter.hpp b/src/graphics/particle_emitter.hpp
index b481db90d..dc77324e0 100644
--- a/src/graphics/particle_emitter.hpp
+++ b/src/graphics/particle_emitter.hpp
@@ -26,6 +26,7 @@
using namespace irr;
class Material;
+class ParticleKind;
/**
* \brief manages smoke particle effects
@@ -41,18 +42,12 @@ private:
/** The emitters. Access to these is needed to adjust the number of
* particles per second. */
scene::IParticleEmitter *m_emitter;
-
- /** Size of the particles. */
- float m_particle_size;
-
- float m_direction_multiplier;
+
+ ParticleKind *m_particle_type;
public:
- ParticleEmitter (float particleSize, core::vector3df position, Material* material,
- int minParticlesPerSeconds, int maxParticlesPerSecond,
- video::SColor minStartColor, video::SColor maxStartColor,
- int lifeTimeMin, int lifeTimeMax, int maxAngle, int fadeOutTime,
- float directionMultiplier, float minSize, float maxSize,
+
+ ParticleEmitter (ParticleKind* type, core::vector3df position,
scene::ISceneNode* parent = NULL);
virtual ~ParticleEmitter();
virtual void update ();
diff --git a/src/graphics/particle_kind.cpp b/src/graphics/particle_kind.cpp
new file mode 100644
index 000000000..8c4d751b8
--- /dev/null
+++ b/src/graphics/particle_kind.cpp
@@ -0,0 +1,154 @@
+// $Id$
+//
+// SuperTuxKart - a fun racing game with go-kart
+// Copyright (C) 2011 Joerg Henrichs, Marianne Gagnon
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 3
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#include "graphics/particle_kind.hpp"
+
+#include "graphics/material.hpp"
+#include "graphics/material_manager.hpp"
+#include "graphics/irr_driver.hpp"
+#include "io/file_manager.hpp"
+#include "io/xml_node.hpp"
+#include "utils/constants.hpp"
+
+#include
+
+ParticleKind::ParticleKind(const std::string file) : m_min_start_color(255,255,255,255), m_max_start_color(255,255,255,255)
+{
+ // ---- Initial values to prevent readin uninitialized values
+ m_max_size = 0.5;
+ m_min_size = 0.5;
+ m_spread_factor = 0.001;
+ m_shape = EMITTER_POINT;
+ m_material = NULL;
+ m_min_rate = 10;
+ m_max_rate = 10;
+ m_lifetime_min = 400;
+ m_lifetime_max = 400;
+ m_fadeout_time = 400;
+
+
+ // ----- Read XML file
+
+ //std::cout << "==== READING " << file << " ====\n";
+
+ XMLNode* xml = file_manager->createXMLTree(file);
+
+ if (xml == NULL)
+ {
+ throw std::runtime_error("[ParticleKind] Cannot find file " + file);
+ }
+
+ if (xml->getName() != "particles")
+ {
+ delete xml;
+ throw std::runtime_error("[ParticleKind] No main node in smoke.xml");
+ }
+
+ // ------------------------------------------------------------------------
+
+ std::string emitterShape = "point";
+ xml->get("emitter", &emitterShape);
+
+ if (emitterShape == "point")
+ {
+ m_shape = EMITTER_POINT;
+ }
+ else if (emitterShape == "box")
+ {
+ m_shape = EMITTER_BOX;
+ }
+ else
+ {
+ std::cerr << "[ParticleKind] main node has unknown value for attribute 'emitter'\n";
+ m_shape = EMITTER_POINT;
+ }
+
+ // ------------------------------------------------------------------------
+
+ const XMLNode* spreading = xml->getNode("spreading");
+ spreading->get("value", &m_spread_factor);
+
+ //std::cout << "m_spread_factor = " << m_spread_factor << "\n";
+
+ // ------------------------------------------------------------------------
+
+ const XMLNode* material = xml->getNode("material");
+ std::string materialFile;
+ material->get("file", &materialFile);
+
+ if (materialFile.size() == 0)
+ {
+ delete xml;
+ throw std::runtime_error("[ParticleKind] tag has invalid 'file' attribute");
+ }
+
+ m_material = material_manager->getMaterial(materialFile);
+ if (m_material->getTexture() == NULL)
+ {
+ throw std::runtime_error("[ParticleKind] Cannot locate file " + materialFile);
+ }
+
+ // ------------------------------------------------------------------------
+
+ const XMLNode* rate = xml->getNode("rate");
+ rate->get("min", &m_min_rate);
+ rate->get("max", &m_max_rate);
+
+ //std::cout << "m_min_rate = " << m_min_rate << "\n";
+ //std::cout << "m_max_rate = " << m_max_rate << "\n";
+
+ // ------------------------------------------------------------------------
+
+ const XMLNode* lifetime = xml->getNode("lifetime");
+ lifetime->get("min", &m_lifetime_min);
+ lifetime->get("max", &m_lifetime_max);
+
+ //std::cout << "m_lifetime_min = " << m_lifetime_min << "\n";
+ //std::cout << "m_lifetime_max = " << m_lifetime_max << "\n";
+
+ // ------------------------------------------------------------------------
+
+ const XMLNode* size = xml->getNode("size");
+ //size->get("default", &m_particle_size);
+ size->get("min", &m_min_size);
+ size->get("max", &m_max_size);
+
+ //std::cout << "m_particle_size = " << m_particle_size << "\n";
+ //std::cout << "m_min_size = " << m_min_size << "\n";
+ //std::cout << "m_max_size = " << m_max_size << "\n";
+
+ // ------------------------------------------------------------------------
+
+ const XMLNode* color = xml->getNode("color");
+ video::SColor minColor;
+ video::SColor maxColor;
+ color->get("min", &m_min_start_color);
+ color->get("max", &m_max_start_color);
+
+ // ------------------------------------------------------------------------
+
+ const XMLNode* fadeout = xml->getNode("fadeout");
+ fadeout->get("time", &m_fadeout_time);
+
+ //std::cout << "m_fadeout_time = " << m_fadeout_time << "\n";
+
+ // ------------------------------------------------------------------------
+
+ delete xml;
+}
diff --git a/src/graphics/particle_kind.hpp b/src/graphics/particle_kind.hpp
new file mode 100644
index 000000000..ca287a478
--- /dev/null
+++ b/src/graphics/particle_kind.hpp
@@ -0,0 +1,99 @@
+// $Id$
+//
+// SuperTuxKart - a fun racing game with go-kart
+// Copyright (C) 2011 Joerg Henrichs, Marianne Gagnon
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 3
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#ifndef HEADER_PARTICLE_KIND_HPP
+#define HEADER_PARTICLE_KIND_HPP
+
+#include "utils/no_copy.hpp"
+
+#include
+#include "irrlicht.h"
+using namespace irr;
+
+class Material;
+
+enum EmitterShape
+{
+ EMITTER_POINT,
+ EMITTER_BOX
+};
+
+/**
+ * \brief type of particles
+ * \ingroup graphics
+ */
+class ParticleKind : public NoCopy
+{
+private:
+
+ /** Size of the particles. */
+ //float m_particle_size;
+ float m_max_size;
+ float m_min_size;
+
+ float m_spread_factor;
+
+ EmitterShape m_shape;
+
+ Material* m_material;
+
+ /** Minimal emission rate in particles per second */
+ int m_min_rate;
+
+ /** Maximal emission rate in particles per second */
+ int m_max_rate;
+
+ int m_lifetime_min;
+ int m_lifetime_max;
+
+ int m_fadeout_time;
+
+ video::SColor m_min_start_color;
+ video::SColor m_max_start_color;
+
+public:
+
+ ParticleKind(const std::string file);
+ virtual ~ParticleKind() {}
+
+
+ //float getParticleSize() const { return m_particle_size; }
+ float getMaxSize () const { return m_max_size; }
+ float getMinSize () const { return m_min_size; }
+
+ int getMinRate () const { return m_min_rate; }
+ int getMaxRate () const { return m_max_rate; }
+
+ float getSpreadFactor() const { return m_spread_factor; }
+
+ EmitterShape getShape () const { return m_shape; }
+
+ Material* getMaterial () const { return m_material; }
+
+ int getMaxLifetime () const { return m_lifetime_max; }
+ int getMinLifetime () const { return m_lifetime_min; }
+
+ int getFadeoutTime () const { return m_fadeout_time; }
+
+ video::SColor getMinColor() const { return m_min_start_color; }
+ video::SColor getMaxColor() const { return m_max_start_color; }
+};
+#endif
+
+
diff --git a/src/ide/Xcode/STK_XCode.xcodeproj/project.pbxproj b/src/ide/Xcode/STK_XCode.xcodeproj/project.pbxproj
index b0c39c1c4..cf52d0a68 100644
--- a/src/ide/Xcode/STK_XCode.xcodeproj/project.pbxproj
+++ b/src/ide/Xcode/STK_XCode.xcodeproj/project.pbxproj
@@ -57,6 +57,7 @@
953C304E12BEF384005BB4CD /* tutorial_data.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 953C304C12BEF384005BB4CD /* tutorial_data.cpp */; };
953F8B2111F7C13C00205E66 /* scalable_font.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 953F8B1F11F7C13C00205E66 /* scalable_font.cpp */; };
9542FC7712D3BDB000C00366 /* particle_emitter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9542FC7512D3BDB000C00366 /* particle_emitter.cpp */; };
+ 9542FD4C12D3E0D700C00366 /* particle_kind.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9542FD4A12D3E0D700C00366 /* particle_kind.cpp */; };
95453ACA11808B8700A155B9 /* emergency_animation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 95453AC811808B8700A155B9 /* emergency_animation.cpp */; };
9545ABCA11E3E38300D3C37A /* progress_bar_widget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9545ABC811E3E38300D3C37A /* progress_bar_widget.cpp */; };
954E486A11B19C4100B1DF63 /* fribidi.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 954E486911B19C4100B1DF63 /* fribidi.framework */; };
@@ -439,6 +440,8 @@
9540E2570FD5F8FD002985B8 /* no_copy.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = no_copy.hpp; path = ../../utils/no_copy.hpp; sourceTree = SOURCE_ROOT; };
9542FC7512D3BDB000C00366 /* particle_emitter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = particle_emitter.cpp; path = ../../graphics/particle_emitter.cpp; sourceTree = SOURCE_ROOT; };
9542FC7612D3BDB000C00366 /* particle_emitter.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = particle_emitter.hpp; path = ../../graphics/particle_emitter.hpp; sourceTree = SOURCE_ROOT; };
+ 9542FD4A12D3E0D700C00366 /* particle_kind.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = particle_kind.cpp; path = ../../graphics/particle_kind.cpp; sourceTree = SOURCE_ROOT; };
+ 9542FD4B12D3E0D700C00366 /* particle_kind.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = particle_kind.hpp; path = ../../graphics/particle_kind.hpp; sourceTree = SOURCE_ROOT; };
95453AC811808B8700A155B9 /* emergency_animation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = emergency_animation.cpp; path = ../../karts/emergency_animation.cpp; sourceTree = SOURCE_ROOT; };
95453AC911808B8700A155B9 /* emergency_animation.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = emergency_animation.hpp; path = ../../karts/emergency_animation.hpp; sourceTree = SOURCE_ROOT; };
9545ABC811E3E38300D3C37A /* progress_bar_widget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = progress_bar_widget.cpp; path = ../../guiengine/widgets/progress_bar_widget.cpp; sourceTree = SOURCE_ROOT; };
@@ -1251,6 +1254,8 @@
952A153A103F66D600B1895D /* moving_texture.hpp */,
9542FC7512D3BDB000C00366 /* particle_emitter.cpp */,
9542FC7612D3BDB000C00366 /* particle_emitter.hpp */,
+ 9542FD4A12D3E0D700C00366 /* particle_kind.cpp */,
+ 9542FD4B12D3E0D700C00366 /* particle_kind.hpp */,
952A153D103F66D600B1895D /* shadow.cpp */,
952A153E103F66D600B1895D /* shadow.hpp */,
952A153F103F66D600B1895D /* skid_marks.cpp */,
@@ -2726,6 +2731,7 @@
951B50AE12C9698B004F6993 /* xml_writer.cpp in Sources */,
9538A56012CD094200CE3220 /* addon.cpp in Sources */,
9542FC7712D3BDB000C00366 /* particle_emitter.cpp in Sources */,
+ 9542FD4C12D3E0D700C00366 /* particle_kind.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
diff --git a/src/io/xml_node.cpp b/src/io/xml_node.cpp
index 000920fc0..04356b38c 100644
--- a/src/io/xml_node.cpp
+++ b/src/io/xml_node.cpp
@@ -255,6 +255,8 @@ int XMLNode::get(const std::string &attribute, int *value) const
{
std::string s;
if(!get(attribute, &s)) return 0;
+ // FIXME: don't use "atoi", if the number in the attribute is not an int we want an error message,
+ // not silently return 0... easy to get bitten by this
*value = atoi(s.c_str());
return 1;
} // get(int)
diff --git a/src/karts/kart.cpp b/src/karts/kart.cpp
index f9d45d339..d4a5d9385 100644
--- a/src/karts/kart.cpp
+++ b/src/karts/kart.cpp
@@ -31,6 +31,7 @@
#include "graphics/camera.hpp"
#include "graphics/material_manager.hpp"
#include "graphics/particle_emitter.hpp"
+#include "graphics/particle_kind.hpp"
#include "graphics/shadow.hpp"
#include "graphics/skid_marks.hpp"
#include "graphics/slip_stream.hpp"
@@ -55,8 +56,6 @@
# pragma warning(disable:4355)
#endif
-const float SMOKE_PARTICLE_SIZE = 0.33f;
-
/** The kart constructor.
* \param ident The identifier for the kart model to use.
* \param position The position (or rank) for this kart (between 1 and
@@ -86,6 +85,7 @@ Kart::Kart (const std::string& ident, int position,
m_race_position = position;
m_collected_energy = 0;
m_finished_race = false;
+ m_wheel_toggle = 1;
m_finish_time = 0.0f;
m_shadow_enabled = false;
m_shadow = NULL;
@@ -1442,25 +1442,29 @@ void Kart::loadData()
// Attach Particle System
if (UserConfigParams::m_graphical_effects)
{
- core::vector3df position(-getKartWidth()*0.35f, SMOKE_PARTICLE_SIZE*0.25f, -getKartLength()*0.5f);
- m_smoke_system = new ParticleEmitter(SMOKE_PARTICLE_SIZE, position, material_manager->getMaterial("smoke.png"),
- 5 /* min particles */, 10 /* max particles */,
- video::SColor(255,0,0,0) /* min color */,
- video::SColor(255,255,255,255) /* max color */,
- 300 /* lifeTimeMin */, 500 /* lifeTimeMax */, 20 /* max angle */,
- 500 /* fade-out time */, 0.003f, SMOKE_PARTICLE_SIZE/1.5f, SMOKE_PARTICLE_SIZE*1.5f);
+ try
+ {
+ core::vector3df position(-getKartWidth()*0.35f, 0.06, -getKartLength()*0.5f);
+ m_smoke_system = new ParticleEmitter(new ParticleKind(file_manager->getDataFile("smoke.xml")), position);
+ }
+ catch (std::runtime_error& e)
+ {
+ std::cerr << e.what() << std::endl;
+ }
}
m_water_splash_system = new WaterSplash(this);
const float particle_size = 0.25f;
core::vector3df position(0, particle_size*0.25f, -getKartLength()*0.5f);
- m_nitro = new ParticleEmitter(particle_size, position, material_manager->getMaterial("nitro-particle.png"),
- 5 /* min particles */, 10 /* max particles */,
- video::SColor(255,0,0,0) /* min color */,
- video::SColor(255,255,255,255) /* max color */,
- 150 /* lifeTimeMin */, 250 /* lifeTimeMax */, 40 /* max angle */,
- 2500 /* fade-out time */, 0.003f, particle_size/1.5f, particle_size*2.0f,
- getNode());
+
+ try
+ {
+ m_nitro = new ParticleEmitter(new ParticleKind(file_manager->getDataFile("nitro.xml")), position, getNode());
+ }
+ catch (std::runtime_error& e)
+ {
+ std::cerr << e.what() << std::endl;
+ }
m_slipstream = new SlipStream(this);
@@ -1551,16 +1555,15 @@ void Kart::updateGraphics(const Vec3& offset_xyz,
f=250.0f;
m_smoke_system->setCreationRate((m_skidding-1)*f);
- static int left = 1;
- left = 1 - left;
- const btWheelInfo &wi = getVehicle()->getWheelInfo(2 + left);
+ m_wheel_toggle = 1 - m_wheel_toggle;
+ const btWheelInfo &wi = getVehicle()->getWheelInfo(2 + m_wheel_toggle);
Vec3 c = wi.m_raycastInfo.m_contactPointWS;
// FIXME: instead of constantly moving the emitter around, just make it a child of the kart node
// FIXME: the X position is not yet always accurate.
- m_smoke_system->setPosition(core::vector3df(c.getX() + SMOKE_PARTICLE_SIZE*0.25f * (left ? +1 : -1),
+ m_smoke_system->setPosition(core::vector3df(c.getX() + 0.06f * (m_wheel_toggle ? +1 : -1),
c.getY(),
- c.getZ() + SMOKE_PARTICLE_SIZE*0.25f));
+ c.getZ() + 0.06f));
}
if(m_water_splash_system)
diff --git a/src/karts/kart.hpp b/src/karts/kart.hpp
index a14266a54..48aa663ac 100644
--- a/src/karts/kart.hpp
+++ b/src/karts/kart.hpp
@@ -106,6 +106,9 @@ private:
* determine startup boost. */
bool m_has_started;
+ /** For skidding smoke */
+ int m_wheel_toggle;
+
float m_max_gear_rpm; /**