Made skidding more controllable: now once the kart

started to skid, you can influence the turn radius
to a certain degree (stk_config.xml, reduce-turn-min
and -max).


git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@10954 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hikerstk 2012-03-08 23:30:26 +00:00
parent f0e65ed092
commit 73176a8d28
8 changed files with 114 additions and 71 deletions

View File

@ -183,9 +183,9 @@
which is used to reduce the turn angle used to reduce the turn angle. --> which is used to reduce the turn angle used to reduce the turn angle. -->
<skid increase="1.05" decrease="0.95" max="2.5" time-till-max="0.5" <skid increase="1.05" decrease="0.95" max="2.5" time-till-max="0.5"
visual="1.0" visual-time="0" visual="1.0" visual-time="0"
time-till-bonus="1.5 2.5" time-till-bonus="1.5 2.5"
bonus-speed="100 200" bonus-time="3.0 4.0" bonus-speed="100 200" bonus-time="3.0 4.0"
post-skid-rotate-factor="1" reduce-turn-min="0.6" post-skid-rotate-factor="1" reduce-turn-min="0.3"
reduce-turn-max="0.8"/> reduce-turn-max="0.8"/>
<!-- Slipstream: length: How far behind a kart slipstream works <!-- Slipstream: length: How far behind a kart slipstream works

View File

@ -72,13 +72,16 @@ public:
virtual void finishedRace (float time) {}; virtual void finishedRace (float time) {};
virtual bool isPlayerController () const {return false;} virtual bool isPlayerController () const {return false;}
virtual bool isNetworkController() const {return false;} virtual bool isNetworkController() const {return false;}
virtual const irr::core::stringw& getNamePostfix() const;
// ------------------------------------------------------------------------
/** Default: ignore actions. Only PlayerController get them. */ /** Default: ignore actions. Only PlayerController get them. */
virtual void action (PlayerAction action, int value) {} virtual void action (PlayerAction action, int value) {}
// ------------------------------------------------------------------------
/** Callback whenever a new lap is triggered. Used by the AI /** Callback whenever a new lap is triggered. Used by the AI
* to trigger a recomputation of the way to use. */ * to trigger a recomputation of the way to use. */
virtual void newLap (int lap) {} virtual void newLap (int lap) {}
virtual const irr::core::stringw& getNamePostfix() const; // ------------------------------------------------------------------------
virtual void skidBonusTriggered() {}
}; // Controller }; // Controller
#endif #endif

View File

@ -245,6 +245,15 @@ void PlayerController::steer(float dt, int steer_val)
} // steer } // steer
//-----------------------------------------------------------------------------
/** Callback when the skidding bonus is triggered. The player controller
* resets the current steering to 0, which makes the kart easier to control.
*/
void PlayerController::skidBonusTriggered()
{
m_controls->m_steer = 0;
} // skidBonusTriggered
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** Updates the player kart, called once each timestep. /** Updates the player kart, called once each timestep.
*/ */

View File

@ -57,6 +57,7 @@ public:
void handleZipper (bool play_sound); void handleZipper (bool play_sound);
void collectedItem (const Item &item, int add_info=-1, void collectedItem (const Item &item, int add_info=-1,
float previous_energy=0); float previous_energy=0);
virtual void skidBonusTriggered();
virtual void setPosition (int p); virtual void setPosition (int p);
virtual void finishedRace (float time); virtual void finishedRace (float time);
bool isPlayerController() const {return true;} bool isPlayerController() const {return true;}

View File

@ -328,7 +328,7 @@ void Kart::setController(Controller *controller)
m_controller = controller; m_controller = controller;
} // setController } // setController
// ---------------------------------------------------------------------------- // -----------------------------------------------------------------------------
/** Sets the position in race this kart has . /** Sets the position in race this kart has .
* The position in this race for this kart (1<=p<=n) * The position in this race for this kart (1<=p<=n)
*/ */
@ -339,6 +339,7 @@ void Kart::setPosition(int p)
} // setPosition } // setPosition
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
/** Returns a transform that will align an object with the kart: the heading /** Returns a transform that will align an object with the kart: the heading
* and the pitch will be set appropriately. A custom pitch value can be * and the pitch will be set appropriately. A custom pitch value can be
* specified in order to overwrite the terrain pitch (which would be used * specified in order to overwrite the terrain pitch (which would be used
@ -1627,9 +1628,7 @@ void Kart::updatePhysics(float dt)
m_skidding->update(dt, isOnGround(), m_controls.m_steer, m_skidding->update(dt, isOnGround(), m_controls.m_steer,
m_controls.m_skid); m_controls.m_skid);
float steering = m_skidding->getSteering(m_controls.m_steer, float steering = getMaxSteerAngle() * m_skidding->getSteeringFraction();
getMaxSteerAngle());
m_vehicle->setSteeringValue(steering, 0); m_vehicle->setSteeringValue(steering, 0);
m_vehicle->setSteeringValue(steering, 1); m_vehicle->setSteeringValue(steering, 1);
@ -2071,7 +2070,7 @@ void Kart::updateGraphics(float dt, const Vec3& offset_xyz,
m_kart_gfx->resizeBox(KartGFX::KGFX_ZIPPER, getSpeed(), dt); m_kart_gfx->resizeBox(KartGFX::KGFX_ZIPPER, getSpeed(), dt);
Moveable::updateGraphics(dt, center_shift, Moveable::updateGraphics(dt, center_shift,
btQuaternion(m_skidding->getVisualSkidOffset(), btQuaternion(m_skidding->getVisualSkidRotation(),
0, 0)); 0, 0));
/* /*
@ -2105,7 +2104,8 @@ void Kart::updateGraphics(float dt, const Vec3& offset_xyz,
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
btQuaternion Kart::getVisualRotation() const btQuaternion Kart::getVisualRotation() const
{ {
return getRotation() * btQuaternion(m_skidding->getVisualSkidOffset(), 0, 0); return getRotation()
* btQuaternion(m_skidding->getVisualSkidRotation(), 0, 0);
} // getVisualRotation } // getVisualRotation

View File

@ -27,8 +27,9 @@
*/ */
Skidding::Skidding(Kart *kart, const SkiddingProperties *sp) Skidding::Skidding(Kart *kart, const SkiddingProperties *sp)
{ {
m_kart = kart; m_kart = kart;
copyFrom(sp); copyFrom(sp);
m_skid_reduce_turn_delta = m_skid_reduce_turn_max - m_skid_reduce_turn_min;
reset(); reset();
} // Skidding } // Skidding
@ -37,28 +38,61 @@ Skidding::Skidding(Kart *kart, const SkiddingProperties *sp)
*/ */
void Skidding::reset() void Skidding::reset()
{ {
m_skid_time = 0.0f; m_skid_time = 0.0f;
m_skid_state = m_skid_visual_time<=0 ? SKID_OLD : SKID_NONE; m_skid_state = m_skid_visual_time<=0 ? SKID_OLD : SKID_NONE;
m_skid_factor = 1.0f; m_skid_factor = 1.0f;
m_real_steering = 0.0f;
} // reset } // reset
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
float Skidding::getSteering(float steer, float max_steer_angle) /** Computes the actual steering fraction to be used in the physics, and
* stores it in m_real_skidding. This is later used by kart to set the
* physical steering. The real steering takes skidding into account: if the
* kart skids either left or right, the steering fraction is bound by
* reduce-turn-min and reduce-turn-max.
*/
void Skidding::updateSteering(float steer)
{ {
float steering = steer * max_steer_angle; if(m_skid_state==SKID_OLD)
{
float speed = m_kart->getSpeed();
float current_max_speed = m_kart->getCurrentMaxSpeed();
float speed_ratio = speed / current_max_speed;
m_real_steering = steer * m_skid_factor;
m_visual_rotation = m_real_steering /m_skid_max * speed_ratio;
return;
}
// Now only new skidding is happening
switch(m_skid_state) switch(m_skid_state)
{ {
case SKID_OLD: assert(false);
break;
case SKID_NONE: case SKID_NONE:
case SKID_SHOW_GFX: m_real_steering = steer;
case SKID_OLD: steering *= m_skid_factor; break;
case SKID_ACCUMULATE_LEFT: case SKID_SHOW_GFX_RIGHT:
case SKID_ACCUMULATE_RIGHT: case SKID_ACCUMULATE_RIGHT:
steering *= m_skid_reduce_turn_min {
* sqrt(m_skid_max / m_skid_factor); float f = (1.0f+steer)*0.5f; // map [-1,1] --> [0, 1]
m_real_steering = m_skid_reduce_turn_min+
m_skid_reduce_turn_delta*f;
break;
}
case SKID_SHOW_GFX_LEFT:
case SKID_ACCUMULATE_LEFT:
{
float f = (-1.0f+steer)*0.5f; // map [-1,1] --> [-1, 0]
m_real_steering = -m_skid_reduce_turn_min+
m_skid_reduce_turn_delta*f;
break;
}
} // switch m_skid_state } // switch m_skid_state
return steering; m_visual_rotation = m_skid_visual * m_real_steering;
} // getSteering
float st = fabsf(m_skid_time);
if(st<m_skid_visual_time)
m_visual_rotation *= st/m_skid_visual_time;
} // updateSteering
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
/** Updates skidding status. /** Updates skidding status.
@ -92,6 +126,7 @@ void Skidding::update(float dt, bool is_on_ground,
else else
if(m_skid_factor<1.0f) m_skid_factor = 1.0f; if(m_skid_factor<1.0f) m_skid_factor = 1.0f;
updateSteering(steering);
// FIXME hiker: remove once the new skidding code is finished. // FIXME hiker: remove once the new skidding code is finished.
if(m_skid_state == SKID_OLD) if(m_skid_state == SKID_OLD)
return; return;
@ -103,7 +138,7 @@ void Skidding::update(float dt, bool is_on_ground,
// by m_skid_state: // by m_skid_state:
// SKID_NONE: no skidding is happening. From here SKID_ACCUMULATE // SKID_NONE: no skidding is happening. From here SKID_ACCUMULATE
// is reached when the skid key is pressed. // is reached when the skid key is pressed.
// SKID_ACCUMULATE: // SKID_ACCUMULATE_{LEFT,RIGHT}:
// The kart is still skidding. The skidding time will be // The kart is still skidding. The skidding time will be
// accumulated in m_skid_time, and once the minimum time for a // accumulated in m_skid_time, and once the minimum time for a
// bonus is reached, the "bonus gfx now available" gfx is shown. // bonus is reached, the "bonus gfx now available" gfx is shown.
@ -111,7 +146,7 @@ void Skidding::update(float dt, bool is_on_ground,
// a potential bonus. Also the rotation of the physical body to // a potential bonus. Also the rotation of the physical body to
// be in synch with the graphical kart is started (which is // be in synch with the graphical kart is started (which is
// independently handled in the kart physics). // independently handled in the kart physics).
// SKID_SHOW_GFX // SKID_SHOW_GFX_{LEFT<RIGHT}
// Shows the skidding gfx while the bonus is available. // Shows the skidding gfx while the bonus is available.
// FIXME: what should we do if skid key is pressed while still in // FIXME: what should we do if skid key is pressed while still in
// SKID_SHOW_GFX??? Adjusting the body rotation is difficult. // SKID_SHOW_GFX??? Adjusting the body rotation is difficult.
@ -122,9 +157,14 @@ void Skidding::update(float dt, bool is_on_ground,
case SKID_NONE: case SKID_NONE:
// If skidding is pressed while the kart is going straight, // If skidding is pressed while the kart is going straight,
// do nothing (till the kart starts to steer in one direction). // do nothing (till the kart starts to steer in one direction).
if(!skidding || steering==0) break; // Just testing for the sign of steering can result in unexpected
m_skid_state = steering > 0 ? SKID_ACCUMULATE_LEFT // beahviour, e.g. if a player is still turning left, but already
: SKID_ACCUMULATE_RIGHT; // presses right (it will take a few frames for this steering to
// actuallu take place, see player_controller) - the kart would skid
// to the left. So we test for a 'clear enough' steering direction.
if(!skidding || fabsf(steering)<0.3f) break;
m_skid_state = steering > 0 ? SKID_ACCUMULATE_RIGHT
: SKID_ACCUMULATE_LEFT;
m_skid_time = 0; // fallthrough m_skid_time = 0; // fallthrough
case SKID_ACCUMULATE_LEFT: case SKID_ACCUMULATE_LEFT:
case SKID_ACCUMULATE_RIGHT: case SKID_ACCUMULATE_RIGHT:
@ -136,14 +176,16 @@ void Skidding::update(float dt, bool is_on_ground,
// If at least level 1 bonus is reached, show appropriate gfx // If at least level 1 bonus is reached, show appropriate gfx
if(level>0) m_kart->getKartGFX()->setSkidLevel(level); if(level>0) m_kart->getKartGFX()->setSkidLevel(level);
// If player stops skidding, trigger bonus, and change state to // If player stops skidding, trigger bonus, and change state to
// SKID_SHOW_GFX // SKID_SHOW_GFX_*
if(!skidding) if(!skidding)
{ {
m_skid_state = SKID_SHOW_GFX; m_skid_state = m_skid_state == SKID_ACCUMULATE_LEFT
? SKID_SHOW_GFX_LEFT
: SKID_SHOW_GFX_RIGHT;
float t = (m_skid_time <= m_skid_visual_time) float t = (m_skid_time <= m_skid_visual_time)
? m_skid_time ? m_skid_time
: m_skid_visual_time; : m_skid_visual_time;
float vso = getVisualSkidOffset(); float vso = getVisualSkidRotation();
btVector3 rot(0, vso*m_post_skid_rotate_factor, 0); btVector3 rot(0, vso*m_post_skid_rotate_factor, 0);
m_kart->getVehicle()->setTimedRotation(t, rot); m_kart->getVehicle()->setTimedRotation(t, rot);
// skid_time is used to count backwards for the GFX // skid_time is used to count backwards for the GFX
@ -163,7 +205,8 @@ void Skidding::update(float dt, bool is_on_ground,
} }
break; break;
} // case } // case
case SKID_SHOW_GFX: case SKID_SHOW_GFX_LEFT:
case SKID_SHOW_GFX_RIGHT:
m_skid_time -= dt; m_skid_time -= dt;
if(m_skid_time<=0) if(m_skid_time<=0)
{ {
@ -196,35 +239,3 @@ unsigned int Skidding::getSkidBonus(float *bonus_time,
return m_skid_bonus_speed.size(); return m_skid_bonus_speed.size();
} // getSkidBonusForce } // getSkidBonusForce
// ----------------------------------------------------------------------------
/** 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
{
float speed = m_kart->getSpeed();
float steer_percent = m_kart->getSteerPercent();
float current_max_speed = m_kart->getCurrentMaxSpeed();
if(m_skid_visual_time==0)
{
float speed_ratio = speed / current_max_speed;
float r = m_skid_factor / m_skid_max;
return steer_percent * speed_ratio * r;
}
// New skidding code
float f = m_skid_visual * steer_percent;
//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_skid_visual_time)
f *= st/m_skid_visual_time;
return f;
} // getVisualSkidOffset
/* EOF */

View File

@ -36,6 +36,17 @@ class Skidding : public SkiddingProperties
public: public:
LEAK_CHECK(); LEAK_CHECK();
private: private:
/** This is m_skid_reduce_turn_max - m_skid_reduce_turn_min. */
float m_skid_reduce_turn_delta;
/** This is the actual steering (in fraction of max-steering-angle)
* to be used by this kart. */
float m_real_steering;
/** An additional rotation (heading) of the kart while skidding. This
* is only a graphical effect, the actual physics body is not rotated. */
float m_visual_rotation;
/** Accumulated skidding factor. */ /** Accumulated skidding factor. */
float m_skid_factor; float m_skid_factor;
@ -48,29 +59,38 @@ private:
* SKID_ACCUMULATE_LEFT: Kart is skidding to the left and accumulating * SKID_ACCUMULATE_LEFT: Kart is skidding to the left and accumulating
* for bonus. * for bonus.
* SKID_ACCUMULATE_RIGHT: Similar for turning right * SKID_ACCUMULATE_RIGHT: Similar for turning right
* SKID_SHOW_GFX: Shows the gfx, while the bonus is actibe. */ * SKID_SHOW_GFX_LEFT: Shows the gfx, while the bonus is active,
* and the kart was turning left.
* SKID_SHOW_GFX_RIGHT: Similar for turning right. */
enum {SKID_OLD, SKID_NONE, SKID_ACCUMULATE_LEFT, SKID_ACCUMULATE_RIGHT, enum {SKID_OLD, SKID_NONE, SKID_ACCUMULATE_LEFT, SKID_ACCUMULATE_RIGHT,
SKID_SHOW_GFX} SKID_SHOW_GFX_LEFT, SKID_SHOW_GFX_RIGHT}
m_skid_state; m_skid_state;
/** A read-only pointer to the kart's properties. */ /** A read-only pointer to the kart's properties. */
Kart *m_kart; Kart *m_kart;
unsigned int getSkidBonus(float *bonus_time, float *bonus_speed) const; unsigned int getSkidBonus(float *bonus_time, float *bonus_speed) const;
void updateSteering(float steer);
public: public:
Skidding(Kart *kart, const SkiddingProperties *sp); Skidding(Kart *kart, const SkiddingProperties *sp);
void reset(); void reset();
void update(float dt, bool is_on_ground, float steer, void update(float dt, bool is_on_ground, float steer,
bool skidding); bool skidding);
float getVisualSkidOffset() const; // ----------------------------------------------------------------------
float getSteering(float steer, float max_steer_angle); /** 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. */
float getVisualSkidRotation() const { return m_visual_rotation; };
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
/** Returns the current skid factor in [1, skid_max_for_this_kart]. */ /** Returns the current skid factor in [1, skid_max_for_this_kart]. */
float getSkidFactor() const { return m_skid_factor; } float getSkidFactor() const { return m_skid_factor; }
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
/** Returns true if the kart is skidding. */ /** Returns true if the kart is skidding. */
bool isSkidding() const { return m_skid_factor>1.0f; } bool isSkidding() const { return m_skid_factor>1.0f; }
// ----------------------------------------------------------------------
/** Returns the steering fraction to be used by the physics. This is
* a fraction of the maximum steering angle ( so in [-1, 1]). */
float getSteeringFraction() { return m_real_steering; }
}; // Skidding }; // Skidding

View File

@ -131,7 +131,6 @@ public:
float getSkidReduceTurnMax () const { return m_skid_reduce_turn_max; } float getSkidReduceTurnMax () const { return m_skid_reduce_turn_max; }
}; // SkiddingProperties }; // SkiddingProperties