Made skidding react something faster: instead of the kart deciding which

direction to skid (which can take some time till max steering is reached
because of smoothed steering) the decision is now done in the control.
So now you can start skid left while the wheels are still in 'right'
direction.


git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@11608 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hikerstk 2012-09-19 06:56:56 +00:00
parent 16fe9bdccd
commit ea82c76fbe
10 changed files with 109 additions and 69 deletions

View File

@ -404,7 +404,11 @@ float AIBaseController::normalizeAngle(float angle)
void AIBaseController::setSteering(float angle, float dt)
{
float steer_fraction = angle / m_kart->getMaxSteerAngle();
m_controls->m_skid = doSkid(steer_fraction);
if(!doSkid(steer_fraction))
m_controls->m_skid = KartControl::SC_NONE;
else
m_controls->m_skid = steer_fraction > 0 ? KartControl::SC_RIGHT
: KartControl::SC_LEFT;
float old_steer = m_controls->m_steer;
if (steer_fraction > 1.0f) steer_fraction = 1.0f;

View File

@ -27,19 +27,29 @@
class KartControl
{
public:
/** The current steering value in [-1, 1]. */
float m_steer;
/** Acceleration, in [0, 1]. */
float m_accel;
/** True if the kart brakes. */
bool m_brake;
/** True if the kart activates nitro. */
bool m_nitro;
bool m_skid;
/** The skidding control state: SC_NONE: not pressed;
SC_NO_DIRECTION: pressed, but no steering;
SC_LEFT/RIGHT: pressed in the specified direction. */
enum SkidControl {SC_NONE, SC_NO_DIRECTION, SC_LEFT, SC_RIGHT}
m_skid;
/** True if rescue is selected. */
bool m_rescue;
/** True if fire is selected. */
bool m_fire;
/** True if the kart looks (and shoots) backwards. */
bool m_look_back;
KartControl() : m_steer(0.0f), m_accel(0.0f), m_brake(false),
m_nitro(false), m_skid(false), m_rescue(false),
m_fire(false), m_look_back(false)
KartControl()
{
reset();
}
// ------------------------------------------------------------------------
/** Construct kart control from a Message (i.e. unserialise) */
@ -51,6 +61,19 @@ public:
setButtonsCompressed(c);
} // KartControl(Message*)
// ------------------------------------------------------------------------
/** Resets all controls. */
void reset()
{
m_steer = 0.0f;
m_accel = 0.0f;
m_brake = false;
m_nitro = false;
m_skid = SC_NONE;
m_rescue = false;
m_fire = false;
m_look_back = false;
} // reset
// ------------------------------------------------------------------------
/** Return the serialised size in bytes. */
static int getLength() { return 9; }
// ------------------------------------------------------------------------
@ -74,10 +97,10 @@ public:
{
return (m_brake ? 1 : 0)
+ (m_nitro ? 2 : 0)
+ (m_skid ? 4 : 0)
+ (m_rescue ? 8 : 0)
+ (m_fire ? 16 : 0)
+ (m_look_back ? 32 : 0);
+ (m_rescue ? 4 : 0)
+ (m_fire ? 8 : 0)
+ (m_look_back ? 16 : 0)
+ (m_skid<<5); // m_skid is in {0,1,2,3}
} // getButtonsCompressed
// ------------------------------------------------------------------------
/** Sets the buttons from a compressed representation.
@ -87,10 +110,10 @@ public:
{
m_brake = (c & 1) != 0;
m_nitro = (c & 2) != 0;
m_skid = (c & 4) != 0;
m_rescue = (c & 8) != 0;
m_fire = (c & 16) != 0;
m_look_back = (c & 32) != 0;
m_rescue = (c & 4) != 0;
m_fire = (c & 8) != 0;
m_look_back = (c & 16) != 0;
m_skid = (SkidControl)((c & 96) >> 5);
} // setButtonsCompressed
};

View File

@ -106,15 +106,7 @@ void PlayerController::resetInputState()
m_prev_brake = 0;
m_prev_accel = 0;
m_prev_nitro = false;
m_controls->m_accel = 0.0f;
m_controls->m_brake = false;
m_controls->m_skid = false;
m_controls->m_fire = false;
m_controls->m_look_back = false;
m_controls->m_nitro = false;
m_controls->m_rescue = false;
m_controls->m_steer = 0.0f;
m_controls->reset();
} // resetInputState
// ----------------------------------------------------------------------------
@ -137,7 +129,11 @@ void PlayerController::action(PlayerAction action, int value)
case PA_STEER_LEFT:
m_steer_val_l = value;
if (value)
{
m_steer_val = value;
if(m_controls->m_skid==KartControl::SC_NO_DIRECTION)
m_controls->m_skid = KartControl::SC_LEFT;
}
else
m_steer_val = m_steer_val_r;
@ -145,7 +141,11 @@ void PlayerController::action(PlayerAction action, int value)
case PA_STEER_RIGHT:
m_steer_val_r = -value;
if (value)
m_steer_val = -value;
{
m_steer_val = -value;
if(m_controls->m_skid==KartControl::SC_NO_DIRECTION)
m_controls->m_skid = KartControl::SC_RIGHT;
}
else
m_steer_val = m_steer_val_l;
@ -206,7 +206,15 @@ void PlayerController::action(PlayerAction action, int value)
m_controls->m_look_back = (value!=0);
break;
case PA_DRIFT:
m_controls->m_skid = (value!=0);
if(value==0)
m_controls->m_skid = KartControl::SC_NONE;
else
if(m_steer_val==0)
m_controls->m_skid = KartControl::SC_NO_DIRECTION;
else
m_controls->m_skid = m_steer_val<0
? KartControl::SC_RIGHT
: KartControl::SC_LEFT;
break;
case PA_PAUSE_RACE:
if (value != 0) StateManager::get()->escapePressed();
@ -231,12 +239,15 @@ void PlayerController::steer(float dt, int steer_val)
video::SColor(255, 255, 0, 255), false);
}
static last_steer = 0;
if(stk_config->m_disable_steer_while_unskid &&
!m_controls->m_skid &&
m_controls->m_skid==KartControl::SC_NONE &&
m_kart->getSkidding()->getVisualSkidRotation()!=0)
{
m_controls->m_steer = 0;
m_controls->m_steer = m_kart->getSkidding()->getSteeringWhenSkidding(last_steer);
}
last_steer = m_kart->getSkidding()->getSteeringFraction();
const float STEER_CHANGE = dt/m_kart->getTimeFullSteer(); // amount the steering is changed
if (steer_val < 0)
{

View File

@ -2140,7 +2140,11 @@ bool SkiddingAI::doSkid(float steer_fraction)
void SkiddingAI::setSteering(float angle, float dt)
{
float steer_fraction = angle / m_kart->getMaxSteerAngle();
m_controls->m_skid = doSkid(steer_fraction);
if(!doSkid(steer_fraction))
m_controls->m_skid = KartControl::SC_NONE;
else
m_controls->m_skid = steer_fraction > 0 ? KartControl::SC_RIGHT
: KartControl::SC_LEFT;
// Adjust steer fraction in case to be in [-1,1]
if (steer_fraction > 1.0f) steer_fraction = 1.0f;
@ -2163,7 +2167,7 @@ void SkiddingAI::setSteering(float angle, float dt)
if((ss==Skidding::SKID_ACCUMULATE_LEFT && steer_fraction>0.2f ) ||
(ss==Skidding::SKID_ACCUMULATE_RIGHT && steer_fraction<-0.2f) )
{
m_controls->m_skid = false;
m_controls->m_skid = KartControl::SC_NONE;
#ifdef DEBUG
if(m_ai_debug)
printf("[AI] skid : '%s' wrong steering, stop skid.\n",
@ -2171,19 +2175,20 @@ void SkiddingAI::setSteering(float angle, float dt)
#endif
}
if(m_controls->m_skid && ( ss==Skidding::SKID_ACCUMULATE_LEFT ||
ss==Skidding::SKID_ACCUMULATE_RIGHT ) )
if(m_controls->m_skid!=KartControl::SC_NONE &&
( ss==Skidding::SKID_ACCUMULATE_LEFT ||
ss==Skidding::SKID_ACCUMULATE_RIGHT ) )
{
steer_fraction =
skidding->getSteeringWhenSkidding(steer_fraction);
if(fabsf(steer_fraction)>1.8)
{
#ifdef DEBUG
if(m_ai_debug)
printf("[AI] skid: %s steering too much (%f).\n",
m_kart->getIdent().c_str(), steer_fraction);
if(m_ai_debug)
printf("[AI] skid: %s steering too much (%f).\n",
m_kart->getIdent().c_str(), steer_fraction);
#endif
m_controls->m_skid = false;
m_controls->m_skid = KartControl::SC_NONE;
}
if(steer_fraction<-1.0f)
steer_fraction = -1.0f;

View File

@ -354,13 +354,7 @@ void Kart::reset()
if(m_engine_sound)
m_engine_sound->stop();
m_controls.m_steer = 0.0f;
m_controls.m_accel = 0.0f;
m_controls.m_brake = false;
m_controls.m_nitro = false;
m_controls.m_skid = false;
m_controls.m_fire = false;
m_controls.m_look_back = false;
m_controls.reset();
m_slipstream->reset();
if(m_vehicle)
{

View File

@ -169,12 +169,13 @@ float Skidding::getSteeringWhenSkidding(float steering) const
* \param skidding True if the skid button is pressed.
*/
void Skidding::update(float dt, bool is_on_ground,
float steering, bool skidding)
float steering, KartControl::SkidControl skidding)
{
m_skid_bonus_ready = false;
if (is_on_ground)
{
if((fabs(steering) > 0.001f) && skidding)
if((fabs(steering) > 0.001f) &&
(skidding==KartControl::SC_LEFT||skidding==KartControl::SC_RIGHT))
{
m_skid_factor += m_skid_increase *dt/m_time_till_max_skid;
}
@ -237,23 +238,12 @@ void Skidding::update(float dt, bool is_on_ground,
{
case SKID_NONE:
{
// If skidding is pressed while the kart is going straight,
// do nothing (till the kart starts to steer in one direction).
// Just testing for the sign of steering can result in unexpected
// behaviour, e.g. if a player is still turning left, but already
// presses right (it will take a few frames for this steering to
// actually take place, see player_controller) - the kart would
// skid to the left. So we test for a 'clear enough' steering
// direction. On the other hand, the AI takes care of that (i.e.
// only skids when steering is already in the right direction) -
// so we allow the AI to change steering even if steering is
// less than 90%.
if(!skidding ||
(m_kart->getController()->isPlayerController() &&
fabsf(steering)<0.9f) )
break;
m_skid_state = steering > 0 ? SKID_ACCUMULATE_RIGHT
: SKID_ACCUMULATE_LEFT;
if(skidding!=KartControl::SC_LEFT &&
skidding!=KartControl::SC_RIGHT)
break;
m_skid_state = skidding==KartControl::SC_RIGHT
? SKID_ACCUMULATE_RIGHT
: SKID_ACCUMULATE_LEFT;
// Add a little jump to the kart. Determine the vertical speed
// necessary for the kart to go 0.5*jump_time up (then it needs
// the same time to come down again), based on v = gravity * t.
@ -338,7 +328,7 @@ void Skidding::update(float dt, bool is_on_ground,
}
// If player stops skidding, trigger bonus, and change state to
// SKID_SHOW_GFX_*
if(!skidding)
if(skidding == KartControl::SC_NONE)
{
m_skid_state = m_skid_state == SKID_ACCUMULATE_LEFT
? SKID_SHOW_GFX_LEFT

View File

@ -19,7 +19,8 @@
#ifndef HEADER_SKIDDING_HPP
#define HEADER_SKIDDING_HPP
#include "skidding_properties.hpp"
#include "karts/skidding_properties.hpp"
#include "karts/controller/kart_control.hpp"
#include "utils/leak_check.hpp"
#include "utils/no_copy.hpp"
@ -105,7 +106,7 @@ public:
~Skidding();
void reset();
void update(float dt, bool is_on_ground, float steer,
bool skidding);
KartControl::SkidControl skidding);
// ------------------------------------------------------------------------
/** Determines how much the graphics model of the kart should be rotated
* additionally (for skidding), depending on how long the kart has been

View File

@ -52,7 +52,10 @@ protected:
struct KartReplayEvent
{
/** The type of event. */
enum KartReplayEventType {KRE_NONE, KRE_SKID_TOGGLE} m_type;
enum KartReplayEventType {KRE_NONE,
KRE_SKID_LEFT,
KRE_SKID_MIN = KRE_SKID_LEFT,
KRE_SKID_RIGHT, KRE_SKID_RELEASE} m_type;
/** Time at which this event happens. */
float m_time;

View File

@ -52,7 +52,7 @@ void ReplayRecorder::init()
{
m_transform_events.clear();
m_transform_events.resize(race_manager->getNumberOfKarts());
m_skid_control.resize(race_manager->getNumberOfKarts(), false);
m_skid_control.resize(race_manager->getNumberOfKarts());
m_kart_replay_event.resize(race_manager->getNumberOfKarts());
for(unsigned int i=0; i<race_manager->getNumberOfKarts(); i++)
{
@ -85,7 +85,7 @@ void ReplayRecorder::reset()
*/
void ReplayRecorder::update(float dt)
{
World *world = World::getWorld();
const World *world = World::getWorld();
unsigned int num_karts = world->getNumKarts();
float time = world->getTime();
@ -101,9 +101,17 @@ void ReplayRecorder::update(float dt)
{
KartReplayEvent kre;
kre.m_time = World::getWorld()->getTime();
kre.m_type = KartReplayEvent::KRE_SKID_TOGGLE;
if(kart->getControls().m_skid==KartControl::SC_LEFT)
kre.m_type = KartReplayEvent::KRE_SKID_LEFT;
else if(kart->getControls().m_skid==KartControl::SC_RIGHT)
kre.m_type = KartReplayEvent::KRE_SKID_RIGHT;
else
kre.m_type = KartReplayEvent::KRE_NONE;
m_kart_replay_event[i].push_back(kre);
m_skid_control[i] = ! m_skid_control[i];
if(m_skid_control[i]!=KartControl::SC_NONE)
m_skid_control[i] = KartControl::SC_NONE;
else
m_skid_control[i] = kart->getControls().m_skid;
}
#ifdef DEBUG
m_count ++;

View File

@ -19,6 +19,7 @@
#ifndef HEADER_REPLAY_RECORDER_HPP
#define HEADER_REPLAY_RECORDER_HPP
#include "karts/controller/kart_control.hpp"
#include "replay/replay_base.hpp"
#include <vector>
@ -40,7 +41,7 @@ private:
std::vector<unsigned int> m_count_transforms;
/** Stores the last skid state. */
std::vector<bool> m_skid_control;
std::vector<KartControl::SkidControl> m_skid_control;
std::vector< std::vector<KartReplayEvent> > m_kart_replay_event;