Moved all slipstream handling from kart into slipstream

(also started to add debug features).


git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@6708 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hikerstk 2010-11-24 05:57:06 +00:00
parent daf2bc5e7e
commit e73ca4bbee
6 changed files with 249 additions and 179 deletions

View File

@ -274,6 +274,9 @@ namespace UserConfigParams
/** Special debug camera being high over the kart. */
PARAM_PREFIX bool m_camera_debug PARAM_DEFAULT( false );
/** True if slipstream debugging is activated. */
PARAM_PREFIX bool m_slipstream_debug PARAM_DEFAULT( false );
/** Verbosity level for debug messages. Note that error and important warnings
* must always be printed. */
PARAM_PREFIX int m_verbosity PARAM_DEFAULT( 0 );

View File

@ -23,6 +23,8 @@
#include "graphics/irr_driver.hpp"
#include "io/file_manager.hpp"
#include "karts/kart.hpp"
#include "modes/world.hpp"
#include "tracks/quad.hpp"
#include "utils/constants.hpp"
/** Creates the slip stream object using a moving texture.
@ -39,8 +41,6 @@ SlipStream::SlipStream(Kart* kart) : MovingTexture(0, 0), m_kart(kart)
m.ColorMaterial = video::ECM_DIFFUSE_AND_AMBIENT;
//m.MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;
//m.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
m.MaterialType = video::EMT_TRANSPARENT_ADD_COLOR;
createMesh(m);
@ -54,6 +54,29 @@ SlipStream::SlipStream(Kart* kart) : MovingTexture(0, 0), m_kart(kart)
m_kart->getKartLength()) );
m_node->setVisible(false);
setTextureMatrix(&(m_node->getMaterial(0).getTextureMatrix(0)));
if(UserConfigParams::m_slipstream_debug)
{
video::SMaterial material;
m_debug_mesh = irr_driver->createQuadMesh(&material, true);
m_debug_node = irr_driver->addMesh(m_debug_mesh);
}
else
{
m_debug_mesh = NULL;
m_debug_node = NULL;
}
m_slipstream_time = 0.0f;
float length = m_kart->getKartProperties()->getSlipstreamLength();
float kw = m_kart->getKartWidth();
float kl = m_kart->getKartLength();
Vec3 p0(-kw*0.5f, 0, -kl*0.5f );
Vec3 p1(-kw*0.5f, 0, -kl*0.5f-length);
Vec3 p2( kw*0.5f, 0, -kl*0.5f-length);
Vec3 p3( kw*0.5f, 0, -kl*0.5f );
m_slipstream_original_quad = new Quad(p0, p1, p2, p3);
m_slipstream_quad = new Quad(p0, p1, p2, p3);
} // SlipStream
//-----------------------------------------------------------------------------
@ -62,8 +85,23 @@ SlipStream::SlipStream(Kart* kart) : MovingTexture(0, 0), m_kart(kart)
SlipStream::~SlipStream()
{
irr_driver->removeNode(m_node);
if(m_debug_node)
{
irr_driver->removeNode(m_debug_node);
m_debug_mesh->drop();
}
delete m_slipstream_original_quad;
delete m_slipstream_quad;
} // ~SlipStream
//-----------------------------------------------------------------------------
/** Called at re-start of a race. */
void SlipStream::reset()
{
m_slipstream_mode = SS_NONE;
} // reset
//-----------------------------------------------------------------------------
/** Creates the mesh for the slipstream effect. This function creates a
* first a series of circles (with a certain number of vertices each and
@ -196,6 +234,41 @@ void SlipStream::setIntensity(float f, const Kart *kart)
MovingTexture::setSpeed(1.0f, 0.0f);
} // setIntensity
//-----------------------------------------------------------------------------
/** Returns true if enough slipstream credits have been accumulated
* to get a boost when leaving the slipstream area.
*/
bool SlipStream::isSlipstreamReady() const
{
return m_slipstream_time>
m_kart->getKartProperties()->getSlipstreamCollectTime();
} // isSlipstreamReady
//-----------------------------------------------------------------------------
/** Returns the additional force being applied to the kart because of
* slipstreaming.
*/
float SlipStream::getSlipstreamPower()
{
// Low level AIs should not do any slipstreaming.
if(!m_kart->getController()->isPlayerController() &&
race_manager->getDifficulty()==RaceManager::RD_EASY) return 0;
// First see if we are currently using accumulated slipstream credits:
// -------------------------------------------------------------------
if(m_slipstream_mode==SS_USE)
{
setIntensity(2.0f, NULL);
const KartProperties *kp=m_kart->getKartProperties();
m_kart->increaseMaxSpeed(MaxSpeed::MS_INCREASE_SLIPSTREAM,
kp->getSlipstreamMaxSpeedIncrease(),
kp->getSlipstreamDuration(),
kp->getSlipstreamFadeOutTime() );
return kp->getSlipstreamAddPower();
}
return 0;
} // getSlipstreamPower
//-----------------------------------------------------------------------------
/** Update, called once per timestep.
* \param dt Time step size.
@ -203,6 +276,112 @@ void SlipStream::setIntensity(float f, const Kart *kart)
void SlipStream::update(float dt)
{
MovingTexture::update(dt);
// Update this karts slipstream quad (even for low level AI which don't
// use slipstream, since even then player karts can get slipstream,
// and so have to compare with the modified slipstream quad.
m_slipstream_original_quad->transform(m_kart->getTrans(),
m_slipstream_quad);
if(m_slipstream_mode==SS_USE)
{
m_slipstream_time -= dt;
if(m_slipstream_time<0) m_slipstream_mode=SS_NONE;
}
// If this kart is too slow for slipstreaming taking effect, do nothing
// --------------------------------------------------------------------
// Define this to get slipstream effect shown even when the karts are
// not moving. This is useful for debugging the graphics of SS-ing.
#undef DISPLAY_SLIPSTREAM_WITH_0_SPEED_FOR_DEBUGGING
#ifndef DISPLAY_SLIPSTREAM_WITH_0_SPEED_FOR_DEBUGGING
if(m_kart->getSpeed()<m_kart->getKartProperties()->getSlipstreamMinSpeed())
{
setIntensity(0, NULL);
m_slipstream_mode = SS_NONE;
return;
}
#endif
// Then test if this kart is in the slipstream range of another kart:
// ------------------------------------------------------------------
World *world = World::getWorld();
unsigned int num_karts = world->getNumKarts();
bool is_sstreaming = false;
m_target_kart = NULL;
// Note that this loop can not be simply replaced with a shorter loop
// using only the karts with a better position - since a kart might
// be a lap behind
for(unsigned int i=0; i<num_karts; i++)
{
m_target_kart= world->getKart(i);
// Don't test for slipstream with itself.
if(m_target_kart==m_kart ||
m_target_kart->isEliminated() ) continue;
// If the kart we are testing against is too slow, no need to test
// slipstreaming. Note: We compare the speed of the other kart
// against the minimum slipstream speed kart of this kart - not
// entirely sure if this makes sense, but it makes it easier to
// give karts different slipstream properties.
#ifndef DISPLAY_SLIPSTREAM_WITH_0_SPEED_FOR_DEBUGGING
if(m_target_kart->getSpeed() <
m_kart->getKartProperties()->getSlipstreamMinSpeed())
continue;
#endif
// Quick test: the kart must be not more than
// slipstream length+kart_length() away from the other kart
Vec3 delta = m_kart->getXYZ() - m_target_kart->getXYZ();
float l = m_target_kart->getKartProperties()->getSlipstreamLength()
+ m_target_kart->getKartLength()*0.5f;
if(delta.length2_2d() > l*l) continue;
// Real test: if in slipstream quad of other kart
if(m_target_kart->getSlipstream()->m_slipstream_quad
->pointInQuad(m_kart->getXYZ()))
{
is_sstreaming = true;
break;
}
} // for i < num_karts
if(!is_sstreaming)
{
if(isSlipstreamReady())
{
// The first time slipstream is ready after collecting
// and you are leaving the slipstream area, you get a
// zipper bonus.
if(m_slipstream_mode==SS_COLLECT)
{
m_slipstream_mode = SS_USE;
m_kart->handleZipper();
m_slipstream_time =
m_kart->getKartProperties()->getSlipstreamCollectTime();
return;
}
}
m_slipstream_time -=dt;
if(m_slipstream_time<0) m_slipstream_mode = SS_NONE;
setIntensity(0, NULL);
return;
} // if !is_sstreaming
// Accumulate slipstream credits now
m_slipstream_time = m_slipstream_mode==SS_NONE ? dt
: m_slipstream_time+dt;
if(isSlipstreamReady())
m_kart->setSlipstreamEffect(3.0f);
setIntensity(m_slipstream_time, m_target_kart);
m_slipstream_mode = SS_COLLECT;
if(m_slipstream_time>m_kart->getKartProperties()->getSlipstreamCollectTime())
{
setIntensity(1.0f, m_target_kart);
}
return;
core::vector3df pos = m_kart->getNode()->getPosition();
pos.Y = m_kart->getHoT()+0.2f;

View File

@ -27,6 +27,7 @@ using namespace irr;
#include "utils/no_copy.hpp"
class Kart;
class Quad;
/**
* \ingroup graphics
@ -43,6 +44,12 @@ private:
/** The actual mesh. */
scene::IMesh *m_mesh;
/** For debugging: display where slipstream works. */
scene::IMeshSceneNode *m_debug_node;
/** For debugging: a simple quad to display where slipstream works. */
scene::IMesh *m_debug_mesh;
/** The texture matrix for the slipstream effect. */
core::matrix4 *m_matrix;
@ -50,12 +57,46 @@ private:
* the actual scene node correctly. */
float m_length;
/** The time a kart was in slipstream. */
float m_slipstream_time;
/** Slipstream mode: either nothing happening, or the kart is collecting
* 'slipstream credits', or the kart is using accumulated credits. */
enum {SS_NONE, SS_COLLECT, SS_USE} m_slipstream_mode;
void createMesh(const video::SMaterial &m);
/** The quad inside which another kart is considered to be slipstreaming.
* This value is current area, i.e. takes the kart position into account. */
Quad *m_slipstream_quad;
/** This is slipstream area if the kart is at 0,0,0 without rotation. From
* this value m_slipstream_area is computed by applying the kart transform. */
Quad *m_slipstream_original_quad;
/** The kart from which this kart gets slipstream. Used by the AI to
** overtake the right kart. */
Kart *m_target_kart;
public:
SlipStream (Kart* kart);
virtual ~SlipStream ();
void reset();
virtual void update(float dt);
void setIntensity(float f, const Kart* kart);
float getSlipstreamPower();
bool isSlipstreamReady() const;
// ------------------------------------------------------------------------
/** Returns the quad in which slipstreaming is effective for
* this kart. */
const Quad& getSlipstreamQuad() const { return *m_slipstream_quad; }
// ------------------------------------------------------------------------
/** Returns the kart from which slipstream is 'collected'. */
const Kart* getSlipstreamTarget() const {return m_target_kart;}
// ------------------------------------------------------------------------
/** Returns if slipstream is being used. */
bool inUse() const {return m_slipstream_mode==SS_USE; }
}; // SlipStream
#endif

View File

@ -39,6 +39,7 @@
#ifdef AI_DEBUG
# include "graphics/irr_driver.hpp"
#endif
#include "graphics/slip_stream.hpp"
#include "modes/linear_world.hpp"
#include "network/network_manager.hpp"
#include "race/race_manager.hpp"
@ -803,16 +804,17 @@ void DefaultAIController::checkCrashes(int steps, const Vec3& pos )
m_crashes.clear();
// If slipstream should be handled actively, trigger overtaking the
// kart which gives us slipstream if slipstream is readyA
if(m_make_use_of_slipstream && m_kart->isSlipstreamReady() &&
m_kart->getSlipstreamKart())
// kart which gives us slipstream if slipstream is ready
const SlipStream *slip=m_kart->getSlipstream();
if(m_make_use_of_slipstream && slip->isSlipstreamReady() &&
slip->getSlipstreamTarget())
{
//printf("%s overtaking %s\n", m_kart->getIdent().c_str(),
// m_kart->getSlipstreamKart()->getIdent().c_str());
// FIXME: we might define a minimum distance, and if the target kart
// is too close break first - otherwise the AI hits the kart when
// trying to overtake it, actually speeding the other kart up.
m_crashes.m_kart = m_kart->getSlipstreamKart()->getWorldKartId();
m_crashes.m_kart = slip->getSlipstreamTarget()->getWorldKartId();
}
const size_t NUM_KARTS = m_world->getNumKarts();
@ -890,9 +892,11 @@ void DefaultAIController::findNonCrashingPoint(Vec3 *result)
float distance;
int steps;
int count=0;
//We exit from the function when we have found a solution
while( 1 )
{
count ++;
//target_sector is the sector at the longest distance that we can drive
//to without crashing with the track.
target_sector = m_next_node_index[sector];
@ -925,6 +929,7 @@ void DefaultAIController::findNonCrashingPoint(Vec3 *result)
if ( distance + m_kart_width * 0.5f
> m_quad_graph->getNode(sector).getPathWidth() )
{
printf("Steps %d\n", count);
*result = m_quad_graph->getQuad(sector).getCenter();
return;
}

View File

@ -92,7 +92,6 @@ Kart::Kart (const std::string& ident, int position,
m_water_splash_system = NULL;
m_nitro = NULL;
m_slipstream = NULL;
m_slipstream_time = 0.0f;
m_skidmarks = NULL;
m_camera = NULL;
m_controller = NULL;
@ -136,14 +135,6 @@ Kart::Kart (const std::string& ident, int position,
}
loadData();
float length = m_kart_properties->getSlipstreamLength();
Vec3 p0(-getKartWidth()*0.5f, 0, -getKartLength()*0.5f );
Vec3 p1(-getKartWidth()*0.5f, 0, -getKartLength()*0.5f-length);
Vec3 p2( getKartWidth()*0.5f, 0, -getKartLength()*0.5f-length);
Vec3 p3( getKartWidth()*0.5f, 0, -getKartLength()*0.5f );
m_slipstream_original_quad = new Quad(p0, p1, p2, p3);
m_slipstream_quad = new Quad(p0, p1, p2, p3);
reset();
} // Kart
@ -342,8 +333,6 @@ Kart::~Kart()
{
delete m_kart_chassis.getChildShape(i);
}
delete m_slipstream_original_quad;
delete m_slipstream_quad;
delete m_kart_model;
} // ~Kart
@ -440,7 +429,6 @@ void Kart::reset()
m_bounce_back_time = 0.0f;
m_skidding = 1.0f;
m_time_last_crash = 0.0f;
m_slipstream_mode = SS_NONE;
if(m_terrain_sound)
{
@ -674,6 +662,8 @@ void Kart::update(float dt)
// if its view is blocked by plunger, decrease remaining time
if(m_view_blocked_by_plunger > 0) m_view_blocked_by_plunger -= dt;
m_slipstream->update(dt);
// Store the actual kart controls at the start of update in the server
// state. This makes it easier to reset some fields when they are not used
// anymore (e.g. controls.fire).
@ -970,141 +960,12 @@ float Kart::handleNitro(float dt)
} // handleNitro
//-----------------------------------------------------------------------------
/** This function manages slipstreaming. It adds up the time a kart was
* slipstreaming, and if a kart was slipstreaming long enough, it will
* add power to the kart for a certain amount of time.
*/
float Kart::handleSlipstream(float dt)
{
// Update this karts slipstream quad (even for low level AI which don't
// use slipstream, since even then player karts can get slipstream,
// and so have to compare with the modified slipstream quad.
m_slipstream_original_quad->transform(getTrans(), m_slipstream_quad);
// Low level AIs should not do any slipstreaming.
if(!getController()->isPlayerController() &&
race_manager->getDifficulty()==RaceManager::RD_EASY) return 0;
// First see if we are currently using accumulated slipstream credits:
// -------------------------------------------------------------------
if(m_slipstream_mode==SS_USE)
{
m_slipstream_time -= dt;
if(m_slipstream_time<0) m_slipstream_mode=SS_NONE;
m_slipstream->setIntensity(2.0f, NULL);
MaxSpeed::increaseMaxSpeed(MaxSpeed::MS_INCREASE_SLIPSTREAM,
m_kart_properties->getSlipstreamMaxSpeedIncrease(),
m_kart_properties->getSlipstreamDuration(),
m_kart_properties->getSlipstreamFadeOutTime() );
return m_kart_properties->getSlipstreamAddPower();
}
// If this kart is too slow for slipstreaming taking effect, do nothing
// --------------------------------------------------------------------
// Define this to get slipstream effect shown even when the karts are
// not moving. This is useful for debugging the graphics of SS-ing.
#undef DISPLAY_SLIPSTREAM_WITH_0_SPEED_FOR_DEBUGGING
#ifndef DISPLAY_SLIPSTREAM_WITH_0_SPEED_FOR_DEBUGGING
if(getSpeed()<m_kart_properties->getSlipstreamMinSpeed())
{
m_slipstream->setIntensity(0, NULL);
return 0;
}
#endif
// Then test if this kart is in the slipstream range of another kart:
// ------------------------------------------------------------------
World *world = World::getWorld();
unsigned int num_karts = world->getNumKarts();
bool is_sstreaming = false;
m_slipstream_target = NULL;
// Note that this loop can not be simply replaced with a shorter loop
// using only the karts with a better position - since a kart might
// be a lap behind
for(unsigned int i=0; i<num_karts; i++)
{
m_slipstream_target= world->getKart(i);
// Don't test for slipstream with itself.
if(m_slipstream_target==this ||
m_slipstream_target->isEliminated() ) continue;
// If the kart we are testing against is too slow, no need to test
// slipstreaming. Note: We compare the speed of the other kart
// against the minimum slipstream speed kart of this kart - not
// entirely sure if this makes sense, but it makes it easier to
// give karts different slipstream properties.
#ifndef DISPLAY_SLIPSTREAM_WITH_0_SPEED_FOR_DEBUGGING
if(m_slipstream_target->getSpeed() <
m_kart_properties->getSlipstreamMinSpeed())
continue;
#endif
// Quick test: the kart must be not more than
// slipstream length+kart_length() away from the other kart
Vec3 delta = getXYZ() - m_slipstream_target->getXYZ();
float l = m_slipstream_target->m_kart_properties->getSlipstreamLength()
+ m_slipstream_target->getKartLength()*0.5f;
if(delta.length2_2d() > l*l) continue;
// Real test: if in slipstream quad of other kart
if(m_slipstream_target->m_slipstream_quad->pointInQuad(getXYZ()))
{
is_sstreaming = true;
break;
}
} // for i < num_karts
if(!is_sstreaming)
{
if(isSlipstreamReady())
{
// The first time slipstream is ready after collecting
// and you are leaving the slipstream area, you get a
// zipper bonus.
if(m_slipstream_mode==SS_COLLECT)
{
m_slipstream_mode = SS_USE;
handleZipper();
// And the time is set to a maximum (to avoid that e.g. AI
// karts slipstream for a long time and then get a very long
// bonus).
m_slipstream_time =
m_kart_properties->getSlipstreamCollectTime();
return m_kart_properties->getSlipstreamAddPower();
}
}
m_slipstream_time -=dt;
if(m_slipstream_time<0) m_slipstream_mode = SS_NONE;
m_slipstream->setIntensity(0, NULL);
return 0;
} // for i<number of karts
// Accumulate slipstream credits now
m_slipstream_time = m_slipstream_mode==SS_NONE ? dt
: m_slipstream_time+dt;
//printf("Collecting slipstream %f\n", m_slipstream_time);
if(isSlipstreamReady())
m_nitro->setCreationRate(3.0f);
m_slipstream->setIntensity(m_slipstream_time, m_slipstream_target);
m_slipstream_mode = SS_COLLECT;
if(m_slipstream_time>m_kart_properties->getSlipstreamCollectTime())
{
m_slipstream->setIntensity(1.0f, m_slipstream_target);
return 0; // see below about abusing zipper without zipper
//return m_kart_properties->getSlipstreamAddPower();
}
return 0;
} // handleSlipstream
// -----------------------------------------------------------------------------
/** Returns true if enough slipstream credits have been accumulated
* to get a boost when leaving the slipstream area.
*/
bool Kart::isSlipstreamReady() const
/** Activates a slipstream effect, atm that is display some nitro. */
void Kart::setSlipstreamEffect(float f)
{
return m_slipstream_time>m_kart_properties->getSlipstreamCollectTime();
} // isSlipstreamReady
m_nitro->setCreationRate(f);
} // setSlipstreamEffect
// -----------------------------------------------------------------------------
/** This function is called when the race starts. Up to then all brakes are
@ -1239,7 +1100,8 @@ void Kart::updatePhysics(float dt)
m_bounce_back_time-=dt;
float engine_power = getActualWheelForce() + handleNitro(dt)
+ handleSlipstream(dt);
+ m_slipstream->getSlipstreamPower();
if(m_attachment->getType()==ATTACH_PARACHUTE) engine_power*=0.2f;
if (m_flying)
@ -1659,7 +1521,7 @@ void Kart::updateGraphics(const Vec3& offset_xyz,
// For testing purposes mis-use the nitro graphical effects to show
// then the slipstream becomes usable.
if(m_slipstream_mode == SS_USE)
if(m_slipstream->inUse())
m_nitro->setCreationRate(20.0f);
float speed_ratio = getSpeed()/MaxSpeed::getCurrentMaxSpeed();

View File

@ -140,7 +140,7 @@ private:
/** Graphical effect when using a nitro. */
Nitro *m_nitro;
/** Graphical effect when slipstreaming. */
/** Handles all slipstreaming. */
SlipStream *m_slipstream;
float m_wheel_rotation;
@ -153,27 +153,6 @@ private:
/** The skidmarks object for this kart. */
SkidMarks *m_skidmarks;
// Variables for slipstreaming
// ---------------------------
/** The quad inside which another kart is considered to be slipstreaming.
* This value is current area, i.e. takes the kart position into account. */
Quad *m_slipstream_quad;
/** This is slipstream area if the kart is at 0,0,0 without rotation. From
* this value m_slipstream_area is computed by applying the kart transform. */
Quad *m_slipstream_original_quad;
/** The time a kart was in slipstream. */
float m_slipstream_time;
/** The kart from which this kart gets slipstream. Used by the AI to
** overtake the right kart. */
Kart *m_slipstream_target;
/** Slipstream mode: either nothing happening, or the kart is collecting
* 'slipstream credits', or the kart is using accumulated credits. */
enum {SS_NONE, SS_COLLECT, SS_USE} m_slipstream_mode;
float m_finish_time;
bool m_finished_race;
@ -194,7 +173,6 @@ private:
SFXBase *m_goo_sound;
float m_time_last_crash;
float handleSlipstream(float dt);
void updatePhysics(float dt);
protected:
@ -219,7 +197,6 @@ public:
void applyEngineForce (float force);
float handleNitro (float dt);
float getActualWheelForce();
bool isSlipstreamReady() const;
virtual void flyUp();
virtual void flyDown();
@ -383,8 +360,11 @@ public:
* from the server information. */
void setSpeed (float s) {m_speed = s; }
// ------------------------------------------------------------------------
/** Returns which kart is giving slip stream to this kart. */
const Kart* getSlipstreamKart() const {return m_slipstream_target;};
/** Returns the slipstream object of this kart. */
const SlipStream* getSlipstream() const {return m_slipstream; }
// ------------------------------------------------------------------------
/** Activates a slipstream effect, atm that is display some nitro. */
void setSlipstreamEffect(float f);
// ------------------------------------------------------------------------
/** Returns a name to be displayed for this kart. */
virtual const irr::core::stringw& getName() const