1) Refactored skidding so that all skidding handling is now done

in a separate object (Skidding) of Kart.
2) Renamed m_drift of the kart control structure to m_skid
   to be consistent with the usage in STK.


git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@10914 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hikerstk 2012-03-02 04:17:38 +00:00
parent 64e49ca09b
commit 88c16e7cbe
13 changed files with 336 additions and 182 deletions

View File

@ -30,6 +30,7 @@
#include "graphics/irr_driver.hpp"
#include "io/xml_node.hpp"
#include "karts/kart.hpp"
#include "karts/skidding.hpp"
#include "modes/world.hpp"
#include "race/race_manager.hpp"
#include "tracks/track.hpp"
@ -320,7 +321,8 @@ void Camera::computeNormalCameraPosition(Vec3 *wanted_position,
// towards where the kart is turning (and turning even more while skidding).
// The skidding effect is dampened.
float steering = m_kart->getSteerPercent()
* (1.0f + (m_kart->getSkidding() - 1.0f)/2.3f );
* (1.0f + (m_kart->getSkidding()->getSkidFactor() - 1.0f)
/2.3f );
// quadratically to dampen small variations (but keep sign)
float dampened_steer = fabsf(steering) * steering;
@ -362,7 +364,8 @@ void Camera::getCameraSettings(float *above_kart, float *cam_angle,
{
*above_kart = 0.75f;
float steering = m_kart->getSteerPercent()
* (1.0f + (m_kart->getSkidding() - 1.0f)/2.3f );
* (1.0f + (m_kart->getSkidding()->getSkidFactor()
- 1.0f)/2.3f );
// quadratically to dampen small variations (but keep sign)
float dampened_steer = fabsf(steering) * steering;
*cam_angle = kp->getCameraForwardUpAngle();
@ -386,7 +389,7 @@ void Camera::getCameraSettings(float *above_kart, float *cam_angle,
*cam_angle = 20.0f*DEGREE_TO_RAD;
*sideway = m_rotation_range
* m_kart->getSteerPercent()
* m_kart->getSkidding();
* m_kart->getSkidding()->getSkidFactor();
*distance = -0.5f*m_distance;
*smoothing = false;
break;

View File

@ -107,7 +107,7 @@ void SkidMarks::update(float dt, bool force_skid_marks,
// ---------------------------------------------------------
if (!force_skid_marks &&
(!raycast_right.m_isInContact ||
!m_kart.getControls().m_drift ||
!m_kart.getControls().m_skid ||
fabsf(m_kart.getControls().m_steer) < 0.001f ||
delta.length2()<0.0001 ) )
{
@ -143,7 +143,7 @@ void SkidMarks::update(float dt, bool force_skid_marks,
// -------------------------
if (!force_skid_marks)
{
if((!m_kart.getControls().m_drift) ||
if((!m_kart.getControls().m_skid) ||
(fabsf(m_kart.getControls().m_steer) < 0.001f))
return; // not skidmarking

View File

@ -868,6 +868,10 @@
RelativePath="..\..\karts\moveable.cpp"
>
</File>
<File
RelativePath="..\..\karts\skidding.cpp"
>
</File>
<Filter
Name="controller"
>
@ -1978,10 +1982,6 @@
RelativePath="..\..\karts\kart.hpp"
>
</File>
<File
RelativePath="..\..\karts\kart_control.hpp"
>
</File>
<File
RelativePath="..\..\karts\kart_gfx.hpp"
>
@ -2010,6 +2010,10 @@
RelativePath="..\..\karts\moveable.hpp"
>
</File>
<File
RelativePath="..\..\karts\skidding.hpp"
>
</File>
<Filter
Name="controller"
>
@ -2029,6 +2033,10 @@
RelativePath="..\..\karts\controller\end_controller.hpp"
>
</File>
<File
RelativePath="..\..\karts\controller\kart_control.hpp"
>
</File>
<File
RelativePath="..\..\karts\controller\new_ai_controller.hpp"
>

View File

@ -307,13 +307,13 @@ float AIBaseController::normalizeAngle(float angle)
void AIBaseController::setSteering(float angle, float dt)
{
float steer_fraction = angle / m_kart->getMaxSteerAngle();
m_controls->m_drift = fabsf(steer_fraction)>=m_skidding_threshold;
if(m_kart->hasViewBlockedByPlunger()) m_controls->m_drift = false;
m_controls->m_skid = fabsf(steer_fraction)>=m_skidding_threshold;
if(m_kart->hasViewBlockedByPlunger()) m_controls->m_skid = false;
// FIXME: Disable skidding for now if the new skidding
// code is activated, since the AI can not handle this
// properly.
if(m_kart->getKartProperties()->getSkidVisualTime()>0)
m_controls->m_drift = false;
m_controls->m_skid = false;
float old_steer = m_controls->m_steer;
if (steer_fraction > 1.0f) steer_fraction = 1.0f;

View File

@ -31,13 +31,13 @@ public:
float m_accel;
bool m_brake;
bool m_nitro;
bool m_drift;
bool m_skid;
bool m_rescue;
bool m_fire;
bool m_look_back;
KartControl() : m_steer(0.0f), m_accel(0.0f), m_brake(false),
m_nitro(false), m_drift(false), m_rescue(false),
m_nitro(false), m_skid(false), m_rescue(false),
m_fire(false), m_look_back(false)
{
}
@ -74,7 +74,7 @@ public:
{
return m_brake ? 1 : 0
+ m_nitro ? 2 : 0
+ m_drift ? 4 : 0
+ m_skid ? 4 : 0
+ m_rescue ? 8 : 0
+ m_fire ? 16 : 0
+ m_look_back ? 32 : 0;
@ -87,7 +87,7 @@ public:
{
m_brake = (c & 1) != 0;
m_nitro = (c & 2) != 0;
m_drift = (c & 4) != 0;
m_skid = (c & 4) != 0;
m_rescue = (c & 8) != 0;
m_fire = (c & 16) != 0;
m_look_back = (c & 32) != 0;

View File

@ -100,7 +100,7 @@ void PlayerController::resetInputState()
m_prev_accel = 0;
m_controls->m_accel = 0.0f;
m_controls->m_brake = false;
m_controls->m_drift = false;
m_controls->m_skid = false;
m_controls->m_fire = false;
m_controls->m_look_back = false;
m_controls->m_nitro = false;
@ -186,7 +186,7 @@ void PlayerController::action(PlayerAction action, int value)
m_controls->m_look_back = (value!=0);
break;
case PA_DRIFT:
m_controls->m_drift = (value!=0);
m_controls->m_skid = (value!=0);
break;
case PA_PAUSE_RACE:
if (value != 0) StateManager::get()->escapePressed();

View File

@ -47,6 +47,7 @@
#include "karts/controller/end_controller.hpp"
#include "karts/kart_model.hpp"
#include "karts/kart_properties_manager.hpp"
#include "karts/skidding.hpp"
#include "modes/linear_world.hpp"
#include "network/race_state.hpp"
#include "network/network_manager.hpp"
@ -186,6 +187,8 @@ Kart::Kart (const std::string& ident, unsigned int world_kart_id,
loadData(type, is_first_kart, animations);
m_kart_gfx = new KartGFX(this);
m_skidding = new Skidding(this);
reset();
} // Kart
@ -542,6 +545,8 @@ void Kart::reset()
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);
@ -553,13 +558,11 @@ void Kart::reset()
m_bubblegum_time = 0.0f;
m_invulnerable_time = 0.0f;
m_squash_time = 0.0f;
m_skid_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_skidding = 1.0f;
m_time_last_crash = 0.0f;
m_speed = 0.0f;
m_view_blocked_by_plunger = 0.0f;
@ -583,7 +586,7 @@ void Kart::reset()
m_controls.m_accel = 0.0f;
m_controls.m_brake = false;
m_controls.m_nitro = false;
m_controls.m_drift = false;
m_controls.m_skid = false;
m_controls.m_fire = false;
m_controls.m_look_back = false;
m_slipstream->reset();
@ -1160,7 +1163,7 @@ void Kart::handleMaterialGFX()
// Get the appropriate particle data depending on
// wether the kart is skidding or driving.
const ParticleKind* pk =
material->getParticlesWhen(m_skidding > 1.0f
material->getParticlesWhen(m_skidding->isSkidding()
? Material::EMIT_ON_SKID
: Material::EMIT_ON_DRIVE);
if(!pk)
@ -1602,7 +1605,8 @@ void Kart::updatePhysics(float dt)
if (m_flying)
updateFlying();
updateSkidding(dt);
m_skidding->update(dt, isOnGround(), m_controls.m_steer,
m_controls.m_skid);
updateSliding();
float steering = getMaxSteerAngle() * m_controls.m_steer;
@ -1610,15 +1614,16 @@ void Kart::updatePhysics(float dt)
// skidding code
if(m_kart_properties->getSkidVisualTime()==0)
{
steering *= m_skidding;
steering *= m_skidding->getSkidFactor();
}
else if(m_controls.m_drift)
else if(m_controls.m_skid)
{
steering *= m_kart_properties->getSkidReduceTurnMin()
* sqrt(m_kart_properties->getMaxSkid()/m_skidding);
steering *= m_kart_properties->getSkidReduceTurnMin()
* sqrt(m_kart_properties->getMaxSkid()
/ m_skidding->getSkidFactor());
}
else
steering *= m_skidding;
steering *= m_skidding->getSkidFactor();
m_vehicle->setSteeringValue(steering, 0);
m_vehicle->setSteeringValue(steering, 1);
@ -1716,112 +1721,6 @@ void Kart::updateEngineSFX()
m_engine_sound->position(getXYZ());
} // updateEngineSFX
//-----------------------------------------------------------------------------
/** Handles skidding.
*/
void Kart::updateSkidding(float dt)
{
// Still going forward while braking: skid a little when the brakes
// are hit (just enough to make the skiding sound)
if(!m_controls.m_accel && m_controls.m_brake && m_speed > 0.0f)
m_skidding *= 1.08f;
if (isOnGround())
{
if((fabs(m_controls.m_steer) > 0.001f) && m_controls.m_drift)
{
m_skidding += m_kart_properties->getSkidIncrease()
*dt/m_kart_properties->getTimeTillMaxSkid();
}
else if(m_skidding>1.0f)
{
m_skidding *= m_kart_properties->getSkidDecrease();
}
}
else
{
m_skidding = 1.0f; // Lose any skid factor as soon as we fly
}
if(m_skidding>m_kart_properties->getMaxSkid())
m_skidding = m_kart_properties->getMaxSkid();
else
if(m_skidding<1.0f) m_skidding=1.0f;
// The skidding sound is played when the kart is actually skidding,
// when it is slowed down due to bubble gum, or when the kart is
// breaking.
if(m_skidding>1.0f || m_bubblegum_time>0 ||
(!m_controls.m_accel && m_controls.m_brake && m_speed > 0.0f) )
{
if(m_skid_sound->getStatus() != SFXManager::SFX_PLAYING &&
m_kart_properties->hasSkidmarks())
m_skid_sound->play();
}
else if(m_skid_sound->getStatus() == SFXManager::SFX_PLAYING)
{
m_skid_sound->stop();
}
// FIXME hiker: remove once the new skidding code is finished.
if(m_kart_properties->getSkidVisualTime()<=0)
return;
// This is only reached if the new skidding is enabled
// ---------------------------------------------------
if(m_controls.m_drift)
{
if(m_skid_time<0) m_skid_time = 0;
m_skid_time += dt;
float bonus_time, bonus_force;
unsigned int level = m_kart_properties->getSkidBonus(m_skid_time,
&bonus_time,
&bonus_force);
// If at least level 1 bonus is reached, show appropriate gfx
if(level>0)
{
m_kart_gfx->setSkidLevel(level);
// Relative 0 means it will emitt the minimum rate, i.e. the rate
// set to indicate that the bonus is now available.
m_kart_gfx->setCreationRateRelative(KartGFX::KGFX_SKID, 0.0f);
}
}
else if(m_skid_time>0)
{
// The kart just stopped skidding - see if a skid bonus applies
float bonus_time, bonus_force;
int level = m_kart_properties->getSkidBonus(m_skid_time,
&bonus_time, &bonus_force);
float t = (m_skid_time <= m_kart_properties->getSkidVisualTime())
? m_skid_time
: m_kart_properties->getSkidVisualTime();
float vso = getVisualSkidOffset();
btVector3 rot(0, vso*m_kart_properties->getPostSkidRotateFactor(), 0);
m_vehicle->setTimedRotation(t, rot);
// Set skid_time to a negative value indicating how long an
// additional rotation is going to be applied to the chassis
m_skid_time = -t;
if(bonus_time>0)
{
MaxSpeed::increaseMaxSpeed(MaxSpeed::MS_INCREASE_SKIDDING,
10, bonus_time, 1);
m_kart_gfx->setCreationRateRelative(KartGFX::KGFX_SKID, 1.0f);
// FIXME hiker: for now just misuse the zipper code
handleZipper(0);
}
else
m_kart_gfx->setCreationRateAbsolute(KartGFX::KGFX_SKID, 0);
}
else if (m_skid_time < 0)
{
m_skid_time += dt;
if(m_skid_time>0)
{
m_skid_time = 0;
m_kart_gfx->setCreationRateAbsolute(KartGFX::KGFX_SKID, 0);
}
}
} // updateSkidding
//-----------------------------------------------------------------------------
/** Sets the engine power. It considers the engine specs, items that influence
* the available power, and braking/steering.
@ -1855,7 +1754,7 @@ void Kart::updateEnginePowerAndBrakes(float dt)
engine_power *= 5.0f;
// Lose some traction when skidding, to balance the adventage
if(m_controls.m_drift)
if(m_controls.m_skid)
engine_power *= 0.5f;
applyEngineForce(engine_power*m_controls.m_accel);
@ -1911,7 +1810,7 @@ void Kart::updateEnginePowerAndBrakes(float dt)
} // not accelerating
} // updateEnginePowerAndBrakes
//-----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
/** Handles sliding, i.e. the kart sliding off terrain that is too steep.
*/
void Kart::updateSliding()
@ -1923,9 +1822,9 @@ void Kart::updateSliding()
float friction = 1.0f;
bool enable_sliding = false;
// This way the current skidding
// handling can be disabled for certain material (e.g. the
// curve in skyline on which otherwise karts could not drive).
// This way the current handling of sliding can be disabled
// for certain material (e.g. the curve in skyline on which otherwise
// karts could not drive).
// We also had a crash reported here, which was caused by not
// having a material here - no idea how this could have happened,
// but this problem is now avoided by testing if there is a material
@ -1963,7 +1862,7 @@ void Kart::updateSliding()
m_vehicle->setSliding(enable_sliding);
} // updateSliding
//-----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
/** Adjusts kart translation if the kart is flying (in debug mode).
*/
void Kart::updateFlying()
@ -2063,7 +1962,9 @@ void Kart::loadData(RaceManager::KartType type, bool is_first_kart,
if(m_kart_properties->hasSkidmarks())
{
m_skidmarks = new SkidMarks(*this);
m_skidmarks->adjustFog( track_manager->getTrack( race_manager->getTrackName() )->isFogEnabled() );
m_skidmarks->adjustFog(
track_manager->getTrack(race_manager->getTrackName())
->isFogEnabled() );
}
m_shadow = new Shadow(m_kart_properties->getShadowTexture(),
@ -2075,7 +1976,7 @@ void Kart::loadData(RaceManager::KartType type, bool is_first_kart,
World::getWorld()->kartAdded(this, m_node);
} // loadData
//-----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
/** Stores the current suspension length. This function is called from world
* after all karts are in resting position (see World::resetAllKarts), so
* that the default suspension rest length can be stored. This is then used
@ -2163,7 +2064,8 @@ void Kart::updateGraphics(float dt, const Vec3& offset_xyz,
m_kart_gfx->resizeBox(KartGFX::KGFX_ZIPPER, getSpeed(), dt);
Moveable::updateGraphics(dt, center_shift,
btQuaternion(getVisualSkidOffset(), 0, 0));
btQuaternion(m_skidding->getVisualSkidOffset(),
0, 0));
/*
// cheap wheelie effect
@ -2196,34 +2098,8 @@ void Kart::updateGraphics(float dt, const Vec3& offset_xyz,
// ----------------------------------------------------------------------------
btQuaternion Kart::getVisualRotation() const
{
return getRotation() * btQuaternion(getVisualSkidOffset(), 0, 0);
return getRotation() * btQuaternion(m_skidding->getVisualSkidOffset(), 0, 0);
} // getVisualRotation
// ----------------------------------------------------------------------------
/** Determines how much the graphics model of the kart should be rotated
* additionally (for skidding), depending on how long the kart has been
* skidding etc.
* \return Returns the angle of the additional rotation of the kart.
*/
float Kart::getVisualSkidOffset() const
{
if(m_kart_properties->getSkidVisualTime()==0)
{
float speed_ratio = getSpeed()/MaxSpeed::getCurrentMaxSpeed();
float r = m_skidding / m_kart_properties->getMaxSkid();
return getSteerPercent() * speed_ratio * r;
}
// New skidding code
float f = m_kart_properties->getSkidVisual() * getSteerPercent();
if(getSpeed() < m_kart_properties->getMaxSpeed())
f *= getSpeed()/m_kart_properties->getMaxSpeed();
float st = fabsf(m_skid_time);
if(st<m_kart_properties->getSkidVisualTime())
f *= st/m_kart_properties->getSkidVisualTime();
return f;
} // getVisualSkidOffset
/* EOF */

View File

@ -51,6 +51,7 @@ class ParticleKind;
class Rain;
class SFXBase;
class Shadow;
class Skidding;
class SkidMarks;
class SlipStream;
@ -67,19 +68,17 @@ class Kart : public TerrainInfo, public Moveable, public EmergencyAnimation,
public MaxSpeed
{
private:
/** True if kart is flying (for debug purposes only). */
bool m_flying;
/** Reset position. */
btTransform m_reset_transform;
/** Index of kart in world. */
unsigned int m_world_kart_id;
/** Accumulated skidding factor. */
float m_skidding;
/** Keeps track on how long a kart has been skidding, in order to
* trigger the skidding bonus. */
float m_skid_time;
/** This object handles all skidding. */
Skidding *m_skidding;
/** The main controller of this object, used for driving. This
* controller is used to run the kart. It will be replaced
@ -200,11 +199,9 @@ private:
void handleMaterialGFX();
void updateFlying();
void updateSliding();
void updateSkidding(float dt);
void updateEnginePowerAndBrakes(float dt);
void updateEngineSFX();
float getVisualSkidOffset() const;
void crashed();
protected:
@ -258,6 +255,9 @@ public:
/** Returns this kart's kart model. */
KartModel* getKartModel() { return m_kart_model; }
// ------------------------------------------------------------------------
/** Returns a points to this kart's graphical effects. */
KartGFX* getKartGFX() { return m_kart_gfx; }
// ------------------------------------------------------------------------
/** Returns the kart properties of this kart. */
const KartProperties*
getKartProperties() const { return m_kart_properties; }
@ -348,8 +348,9 @@ public:
float getMaxSteerAngle () const
{ return m_kart_properties->getMaxSteerAngle(getSpeed()); }
// ------------------------------------------------------------------------
/** Returns the amount of skidding for this kart. */
float getSkidding() const { return m_skidding; }
/** Returns the skidding object for this kart (which can be used to query
* skidding related values). */
const Skidding *getSkidding() const { return m_skidding; }
// ------------------------------------------------------------------------
/** Returns the current steering value for this kart. */
float getSteerPercent() const { return m_controls.m_steer; }

View File

@ -24,6 +24,7 @@
#include "graphics/particle_kind.hpp"
#include "graphics/particle_kind_manager.hpp"
#include "karts/kart.hpp"
#include "karts/skidding.hpp"
#include "physics/btKart.hpp"
#include <iostream>
@ -139,6 +140,9 @@ void KartGFX::setSkidLevel(const unsigned int level)
const ParticleKind *pk = level==1 ? m_skid_kind1 : m_skid_kind2;
if(m_all_emitters[KGFX_SKID1])
m_all_emitters[KGFX_SKID1]->setParticleType(pk);
// Relative 0 means it will emitt the minimum rate, i.e. the rate
// set to indicate that the bonus is now available.
setCreationRateRelative(KartGFX::KGFX_SKID, 0.0f);
} // setSkidLevel
// ----------------------------------------------------------------------------
@ -238,7 +242,7 @@ void KartGFX::updateTerrain(const ParticleKind *pk)
// Now compute the particle creation rate:
float rate = 0;
const float speed = fabsf(m_kart->getSpeed());
const float skidding = m_kart->getSkidding();
const float skidding = m_kart->getSkidding()->getSkidFactor();
if (skidding > 1.0f)
rate = fabsf(m_kart->getControls().m_steer) > 0.8 ? skidding - 1 : 0;
else if (speed >= 0.5f)

View File

@ -682,6 +682,7 @@ public:
/** Returns the factor by which to recude the amount of steering while
skidding. */
float getSkidReduceTurnMin () const { return m_skid_reduce_turn_min; }
float getSkidReduceTurnMax () const { return m_skid_reduce_turn_max; }
/** Returns if the kart leaves skidmarks or not. */
bool hasSkidmarks () const {return m_has_skidmarks; }

View File

@ -58,7 +58,7 @@ void KartWithStats::update(float dt)
{
Kart::update(dt);
if(getSpeed()>m_top_speed) m_top_speed = getSpeed();
if(getControls().m_drift)
if(getControls().m_skid)
m_skidding_time += dt;
} // update

195
src/karts/skidding.cpp Normal file
View File

@ -0,0 +1,195 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2012 Joerg Henrichs
//
// 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 "karts/skidding.hpp"
#include "karts/kart.hpp"
#include "karts/kart_gfx.hpp"
#include "karts/kart_properties.hpp"
#include "physics/btKart.hpp"
/** Constructor of the skidding object.
*/
Skidding::Skidding(Kart *kart)
{
m_kart = kart;
reset();
} // Skidding
// ----------------------------------------------------------------------------
/** Resets all skidding related values.
*/
void Skidding::reset()
{
m_skid_time = 0.0f;
m_skid_state = SKID_NONE;
m_skid_factor = 1.0f;
} // reset
// ----------------------------------------------------------------------------
/** Updates skidding status.
* \param dt Time step size.
* \param is_on_ground True if the kart is on ground.
* \param steering Raw steering of the kart [-1,1], i.e. not adjusted by
* the kart's max steering angle.
* \param skidding True if the skid button is pressed.
*/
void Skidding::update(float dt, bool is_on_ground,
float steering, bool skidding)
{
if (is_on_ground)
{
if((fabs(steering) > 0.001f) && skidding)
{
m_skid_factor += m_kart->getKartProperties()->getSkidIncrease()
*dt/m_kart->getKartProperties()->getTimeTillMaxSkid();
}
else if(m_skid_factor>1.0f)
{
m_skid_factor *= m_kart->getKartProperties()->getSkidDecrease();
}
}
else
{
m_skid_factor = 1.0f; // Lose any skid factor as soon as we fly
}
if(m_skid_factor>m_kart->getKartProperties()->getMaxSkid())
m_skid_factor = m_kart->getKartProperties()->getMaxSkid();
else
if(m_skid_factor<1.0f) m_skid_factor = 1.0f;
// FIXME hiker: remove once the new skidding code is finished.
if(m_kart->getKartProperties()->getSkidVisualTime()<=0)
return;
// This is only reached if the new skidding is enabled
// ---------------------------------------------------
// There are four distinct states related to skidding, controlled
// by m_skid_state:
// SKID_NONE: no skidding is happening. From here SKID_ACCUMULATE
// is reached when the skid key is pressed.
// SKID_ACCUMULATE:
// The kart is still skidding. The skidding time will be
// accumulated in m_skid_time, and once the minimum time for a
// bonus is reached, the "bonus gfx now available" gfx is shown.
// If the skid button is not pressed anymore, this will trigger
// a potential bonus. Also the rotation of the physical body to
// be in synch with the graphical kart is started (which is
// independently handled in the kart physics).
// SKID_SHOW_GFX
// Shows the skidding gfx while the bonus is available.
// FIXME: what should we do if skid key is pressed while still in
// SKID_SHOW_GFX??? Adjusting the body rotation is difficult.
// For now skidding will only start again once SKID_SHOW_GFX
// is changed to SKID_NONE.
switch(m_skid_state)
{
case SKID_NONE:
// If skidding is pressed while the kart is going straight,
// do nothing (till the kart starts to steer in one direction).
if(!skidding || steering==0) break;
m_skid_state = steering > 0 ? SKID_ACCUMULATE_LEFT
: SKID_ACCUMULATE_RIGHT;
m_skid_time = 0; // fallthrough
case SKID_ACCUMULATE_LEFT:
case SKID_ACCUMULATE_RIGHT:
{
m_skid_time += dt;
float bonus_time, bonus_force;
unsigned int level =
m_kart->getKartProperties()->getSkidBonus(m_skid_time,
&bonus_time,
&bonus_force);
// If at least level 1 bonus is reached, show appropriate gfx
if(level>0) m_kart->getKartGFX()->setSkidLevel(level);
// If player stops skidding, trigger bonus, and change state to
// SKID_SHOW_GFX
if(!skidding)
{
m_skid_state = SKID_SHOW_GFX;
float t = (m_skid_time <= m_kart->getKartProperties()
->getSkidVisualTime())
? m_skid_time
: m_kart->getKartProperties()->getSkidVisualTime();
float vso = getVisualSkidOffset();
btVector3 rot(0,
vso*m_kart->getKartProperties()
->getPostSkidRotateFactor(),
0);
m_kart->getVehicle()->setTimedRotation(t, rot);
// skid_time is used to count backwards for the GFX
m_skid_time = t;
if(bonus_time>0)
{
m_kart->MaxSpeed::increaseMaxSpeed(
MaxSpeed::MS_INCREASE_SKIDDING, 10, bonus_time, 1);
m_kart->getKartGFX()
->setCreationRateRelative(KartGFX::KGFX_SKID, 1.0f);
// FIXME hiker: for now just misuse the zipper code
m_kart->handleZipper(0);
}
else
m_kart->getKartGFX()
->setCreationRateAbsolute(KartGFX::KGFX_SKID, 0);
}
break;
} // case
case SKID_SHOW_GFX:
m_skid_time -= dt;
if(m_skid_time<=0)
{
m_skid_time = 0;
m_kart->getKartGFX()
->setCreationRateAbsolute(KartGFX::KGFX_SKID, 0);
m_skid_state = SKID_NONE;
}
} // switch
} // updateSkidding
// ----------------------------------------------------------------------------
/** Determines how much the graphics model of the kart should be rotated
* additionally (for skidding), depending on how long the kart has been
* skidding etc.
* \return Returns the angle of the additional rotation of the kart.
*/
float Skidding::getVisualSkidOffset() const
{
if(m_kart->getKartProperties()->getSkidVisualTime()==0)
{
float speed_ratio = m_kart->getSpeed()
/ m_kart->MaxSpeed::getCurrentMaxSpeed();
float r = m_skid_factor / m_kart->getKartProperties()->getMaxSkid();
return m_kart->getSteerPercent() * speed_ratio * r;
}
// New skidding code
float f = m_kart->getKartProperties()->getSkidVisual()
* m_kart->getSteerPercent();
if(m_kart->getSpeed() < m_kart->getKartProperties()->getMaxSpeed())
f *= m_kart->getSpeed()/m_kart->getKartProperties()->getMaxSpeed();
float st = fabsf(m_skid_time);
if(st<m_kart->getKartProperties()->getSkidVisualTime())
f *= st/m_kart->getKartProperties()->getSkidVisualTime();
return f;
} // getVisualSkidOffset
/* EOF */

66
src/karts/skidding.hpp Normal file
View File

@ -0,0 +1,66 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2012 Joerg Henrichs
//
// 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_SKIDDING_HPP
#define HEADER_SKIDDING_HPP
#include "utils/no_copy.hpp"
class Kart;
/**
* \ingroup karts
*/
class Skidding : public NoCopy
{
private:
/** Accumulated skidding factor. */
float m_skid_factor;
/** Keeps track on how long a kart has been skidding, in order to
* trigger the skidding bonus. */
float m_skid_time;
enum {SKID_NONE, SKID_ACCUMULATE_LEFT, SKID_ACCUMULATE_RIGHT,
SKID_TRIGGER_BONUS, SKID_SHOW_GFX}
m_skid_state;
/** A read-only pointer to the kart's properties. */
Kart *m_kart;
public:
Skidding(Kart *kart);
~Skidding();
void reset();
void update(float dt, bool is_on_ground, float steer,
bool skidding);
float getVisualSkidOffset() const;
// ----------------------------------------------------------------------
/** Returns the current skid factor in [1, skid_max_for_this_kart]. */
float getSkidFactor() const { return m_skid_factor; }
// ----------------------------------------------------------------------
/** Returns true if the kart is skidding. */
bool isSkidding() const { return m_skid_factor>1.0f; }
}; // Skidding
#endif
/* EOF */