Added new object to handle max-speed of karts. ATM it will slow down

depending on terrain, so zipper etc. handling is not yet finished but
will come soon.
Also zipper parameters can now be specified per kart.


git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@6325 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hikerstk
2010-10-25 00:52:50 +00:00
parent 6226a48b6b
commit 0f0c74f391
13 changed files with 442 additions and 92 deletions

View File

@@ -71,12 +71,6 @@
to timer when bomb is passed on. -->
<bomb time="30.0" time-increase="-5.0"/>
<!-- time is the time a zipper is active. force is the additional
zipper force. speed-gain is the one time additional speed.
max-speed-fraction is a factor multiplied to the maximum
speed on the terrain. -->
<zipper time="3.5" force="250.0" speed-gain="4.5" max-speed-fraction="2.0"/>
<!-- Powerup collect-mode decides what is collected if a kart has already an
powerup: same: get one more item of the same type.
new: always get a new item.
@@ -150,6 +144,14 @@
big-container: how much energy a big container gives. -->
<nitro power-boost="3" consumption="1" small-container="1" big-container="3"/>
<!-- time is the time a zipper is active. force is the additional
zipper force. speed-gain is the one time additional speed.
max-speed-increase is the additional speed allowed on top
of the kart-specific maximum kart speed. Fade-out time determines
how long it takes for a zipper to fade out (after 'time'). -->
<zipper time="3.5" force="250.0" speed-gain="4.5" max-speed-increase="15"
fade-out-time="1.0" />
<!-- Skidding: increase: multiplicative increase of skidding factor in each frame.
decrease: multiplicative decrease of skidding factor in each frame.
max: maximum skidding factor = maximum increase of steering angle.

View File

@@ -105,10 +105,6 @@ void STKConfig::load(const std::string &filename)
CHECK_NEG(m_bomb_time_increase, "bomb-time-increase" );
CHECK_NEG(m_anvil_time, "anvil-time" );
CHECK_NEG(m_anvil_weight, "anvil-weight" );
CHECK_NEG(m_zipper_time, "zipper-time" );
CHECK_NEG(m_zipper_force, "zipper-force" );
CHECK_NEG(m_zipper_speed_gain, "zipper-speed-gain" );
CHECK_NEG(m_zipper_max_speed_fraction, "zipper-max-speed-fraction" );
CHECK_NEG(m_item_switch_time, "item-switch-time" );
CHECK_NEG(m_bubble_gum_counter, "bubblegum disappear counter");
CHECK_NEG(m_explosion_impulse, "explosion-impulse" );
@@ -140,9 +136,7 @@ void STKConfig::init_defaults()
m_parachute_time = m_parachute_done_fraction =
m_parachute_time_other = m_anvil_speed_factor =
m_bomb_time = m_bomb_time_increase =
m_anvil_time = m_zipper_time =
m_zipper_force = m_zipper_speed_gain =
m_zipper_max_speed_fraction = m_music_credit_time =
m_anvil_time = m_music_credit_time =
m_explosion_impulse = m_explosion_impulse_objects =
m_delay_finish_time = m_skid_fadeout_time =
m_near_ground = m_item_switch_time =
@@ -283,14 +277,6 @@ void STKConfig::getAllData(const XMLNode * root)
bomb_node->get("time-increase", &m_bomb_time_increase);
}
if(const XMLNode *zipper_node= root->getNode("zipper"))
{
zipper_node->get("time", &m_zipper_time );
zipper_node->get("force", &m_zipper_force );
zipper_node->get("speed-gain", &m_zipper_speed_gain );
zipper_node->get("max-speed-fraction", &m_zipper_max_speed_fraction);
}
if(const XMLNode *powerup_node= root->getNode("powerup"))
{
std::string s;

View File

@@ -66,12 +66,6 @@ public:
float m_bomb_time_increase; /**<Time added to bomb timer when it's
passed on. */
float m_anvil_time; /**<Time an anvil is active. */
float m_zipper_time; /**<Duration a zipper is active. */
float m_zipper_force; /**<Additional force added to the
acceleration. */
float m_zipper_speed_gain; /**<Initial one time speed gain. */
float m_zipper_max_speed_fraction;/**<Fraction of max speed allowed past
regular max speed */
float m_item_switch_time; /**< Time items will be switched. */
int m_bubble_gum_counter; /**< How many times bananas must be eaten
before they disappear. */

View File

@@ -618,6 +618,10 @@
RelativePath="..\..\karts\kart_properties_manager.cpp"
>
</File>
<File
RelativePath="..\..\karts\max_speed.cpp"
>
</File>
<File
RelativePath="..\..\karts\moveable.cpp"
>
@@ -1532,6 +1536,10 @@
RelativePath="..\..\karts\kart_properties_manager.hpp"
>
</File>
<File
RelativePath="..\..\karts\max_speed.hpp"
>
</File>
<File
RelativePath="..\..\karts\moveable.hpp"
>

View File

@@ -93,7 +93,7 @@ DefaultAIController::DefaultAIController(Kart *kart) : AIBaseController(kart)
case RaceManager::RD_EASY:
m_wait_for_players = true;
m_make_use_of_slipstream = false;
m_max_handicap_accel = 0.9f;
m_max_handicap_speed = 0.9f;
m_item_tactic = IT_TEN_SECONDS;
m_false_start_probability = 0.08f;
m_min_start_delay = 0.3f;
@@ -106,7 +106,7 @@ DefaultAIController::DefaultAIController(Kart *kart) : AIBaseController(kart)
case RaceManager::RD_MEDIUM:
m_wait_for_players = true;
m_make_use_of_slipstream = false;
m_max_handicap_accel = 0.95f;
m_max_handicap_speed = 0.95f;
m_item_tactic = IT_CALCULATE;
m_false_start_probability = 0.04f;
m_min_start_delay = 0.25f;
@@ -119,7 +119,7 @@ DefaultAIController::DefaultAIController(Kart *kart) : AIBaseController(kart)
case RaceManager::RD_HARD:
m_wait_for_players = false;
m_make_use_of_slipstream = true;
m_max_handicap_accel = 1.0f;
m_max_handicap_speed = 1.0f;
m_item_tactic = IT_CALCULATE;
m_false_start_probability = 0.01f;
// See http://www.humanbenchmark.com/tests/reactiontime/stats.php
@@ -298,7 +298,8 @@ void DefaultAIController::update(float dt)
// use the zipper instead
if(m_controls->m_nitro &&
m_kart->getPowerup()->getType()==PowerupManager::POWERUP_ZIPPER &&
m_kart->getSpeed()>1.0f && m_kart->getZipperTimeLeft()<=0)
m_kart->getSpeed()>1.0f &&
m_kart->getSpeedIncreaseTimeLeft(MaxSpeed::MS_INCREASE_ZIPPER)<=0)
{
// Make sure that not all AI karts use the zipper at the same
// time in time trial at start up, so during the first 5 seconds
@@ -691,6 +692,11 @@ void DefaultAIController::handleAcceleration( const float dt)
return;
}
// FIXME: this needs to be rewritten, it doesn't make any sense:
// wait for players triggers the opposite (if a player is ahead
// of this AI, go full speed). Besides, it's going to use full
// speed anyway.
if( m_wait_for_players )
{
//Find if any player is ahead of this kart
@@ -704,7 +710,7 @@ void DefaultAIController::handleAcceleration( const float dt)
if( player_winning )
{
m_controls->m_accel = m_max_handicap_accel;
m_controls->m_accel = m_max_handicap_speed;
return;
}
}

View File

@@ -78,9 +78,8 @@ private:
* position than all the human players. */
bool m_wait_for_players;
/** The allowed maximum speed, in percentage, from 0.0 to 1.0. Used only
* when m_wait_for_players == true. */
float m_max_handicap_accel;
/** The allowed maximum speed in percent of the kart's maximum speed. */
float m_max_handicap_speed;
/** How are items going to be used? */
ItemTactic m_item_tactic;

View File

@@ -245,7 +245,8 @@ void NewAIController::update(float dt)
// use the zipper instead
if(m_controls->m_nitro &&
m_kart->getPowerup()->getType()==PowerupManager::POWERUP_ZIPPER &&
m_kart->getSpeed()>1.0f && m_kart->getZipperTimeLeft()<=0)
m_kart->getSpeed()>1.0f &&
m_kart->getSpeedIncreaseTimeLeft(MaxSpeed::MS_INCREASE_ZIPPER)<=0)
{
// Make sure that not all AI karts use the zipper at the same
// time in time trial at start up, so during the first 5 seconds

View File

@@ -64,7 +64,7 @@
Kart::Kart (const std::string& ident, int position,
const btTransform& init_transform)
: TerrainInfo(1),
Moveable(), EmergencyAnimation(this), m_powerup(this)
Moveable(), EmergencyAnimation(this), MaxSpeed(this), m_powerup(this)
#if defined(WIN32) && !defined(__CYGWIN__)
# pragma warning(1:4355)
@@ -343,6 +343,23 @@ void Kart::adjustSpeed(float f)
m_body->setAngularVelocity(m_body->getAngularVelocity()*f);
} // adjustSpeed
//-----------------------------------------------------------------------------
/** Caps the speed at a given value. If necessary the kart will
* instantaneously change its speed.
* \param max_speed Maximum speed of the kart.
*/
void Kart::capSpeed(float max_speed)
{
if ( m_speed > max_speed && isOnGround() )
{
const float velocity_ratio = max_speed/m_speed;
btVector3 velocity = getBody()->getLinearVelocity();
velocity *= velocity_ratio;
getVehicle()->getRigidBody()->setLinearVelocity( velocity );
}
} // capSpeed
//-----------------------------------------------------------------------------
/** This method is to be called every time the mass of the kart is updated,
* which includes attaching an anvil to the kart (and detaching).
@@ -363,7 +380,7 @@ void Kart::updatedWeight()
void Kart::reset()
{
EmergencyAnimation::reset();
MaxSpeed::reset();
if (m_camera)
{
m_camera->reset();
@@ -388,7 +405,6 @@ void Kart::reset()
m_race_position = m_initial_position;
m_finished_race = false;
m_finish_time = 0.0f;
m_zipper_time_left = 0.0f;
m_collected_energy = 0;
m_has_started = false;
m_wheel_rotation = 0;
@@ -574,17 +590,18 @@ void Kart::collectedItem(Item *item, int add_info)
*/
float Kart::getActualWheelForce()
{
float zipperF=(m_zipper_time_left>0.0f) ? stk_config->m_zipper_force : 0.0f;
float time_left = MaxSpeed::getSpeedIncreaseTimeLeft(MS_INCREASE_ZIPPER);
float zipper_force = time_left>0.0f ? m_kart_properties->getZipperForce(): 0.0f;
const std::vector<float>& gear_ratio=m_kart_properties->getGearSwitchRatio();
for(unsigned int i=0; i<gear_ratio.size(); i++)
{
if(m_speed <= m_kart_properties->getMaxSpeed()*gear_ratio[i])
{
return getMaxPower()*m_kart_properties->getGearPowerIncrease()[i]
+zipperF;
+zipper_force;
}
}
return getMaxPower()+zipperF;
return getMaxPower()+zipper_force;
} // getActualWheelForce
@@ -648,7 +665,8 @@ void Kart::update(float dt)
// When really on air, free fly, when near ground, try to glide / adjust for landing
// If zipped, be stable, so ramp+zipper can allow nice jumps without scripting the fly
if(!isNearGround() && !(m_zipper_time_left > 0.0f))
if(!isNearGround() &&
MaxSpeed::getSpeedIncreaseTimeLeft(MS_INCREASE_ZIPPER)<=0.0f )
m_uprightConstraint->setLimit(M_PI);
else
m_uprightConstraint->setLimit(m_kart_properties->getUprightTolerance());
@@ -670,8 +688,6 @@ void Kart::update(float dt)
//m_body->setAngularVelocity(btVector3(0,0,0));
}
m_zipper_time_left = m_zipper_time_left>0.0f ? m_zipper_time_left-dt : 0.0f;
//m_wheel_rotation gives the rotation around the X-axis, and since velocity's
//timeframe is the delta time, we don't have to multiply it with dt.
m_wheel_rotation += m_speed*dt / m_kart_properties->getWheelRadius();
@@ -802,6 +818,9 @@ void Kart::update(float dt)
else if(material->isZipper() && isOnGround()) handleZipper();
else
{
MaxSpeed::setSlowdown(MaxSpeed::MS_DECREASE_TERRAIN,
material->getMaxSpeedFraction(),
material->getSlowDownTime() );
// Normal driving on terrain. Adjust for maximum terrain speed
// Gradually adjust the fraction of the maximum kart speed to
// the amount specified for the terrain.
@@ -841,13 +860,16 @@ void Kart::handleZipper()
{
// Ignore a zipper that's activated while braking
if(m_controls.m_brake) return;
m_zipper_time_left = stk_config->m_zipper_time;
btVector3 v = m_body->getLinearVelocity();
float current_speed = v.length();
float speed = std::min(current_speed+stk_config->m_zipper_speed_gain,
getMaxSpeedOnTerrain() *
(1 + stk_config->m_zipper_max_speed_fraction));
MaxSpeed::increaseMaxSpeed(MaxSpeed::MS_INCREASE_ZIPPER,
m_kart_properties->getZipperMaxSpeedIncrease(),
m_kart_properties->getZipperTime(),
/*fade_out_time*/ 3.0f);
// This will result in all max speed settings updated, but no
// changes to any slow downs since dt=0
MaxSpeed::update(0);
float speed = std::min(m_speed+m_kart_properties->getZipperSpeedGain(),
MaxSpeed::getCurrentMaxSpeed() );
m_vehicle->activateZipper(speed);
// Play custom character sound (weee!)
@@ -988,7 +1010,7 @@ float Kart::handleSlipstream(float dt)
if(m_slipstream_time>m_kart_properties->getSlipstreamCollectTime())
{
m_slipstream->setIntensity(1.0f, m_slipstream_target);
return 0; // see below about abusing m_zipper_time_left without zipper
return 0; // see below about abusing zipper without zipper
//return m_kart_properties->getSlipstreamAddPower();
}
return 0;
@@ -1128,9 +1150,10 @@ void Kart::updatePhysics(float dt)
if(!m_has_started && m_controls.m_accel)
{
m_has_started = true;
m_zipper_time_left = 5.0f;
float f = m_kart_properties->getStartupBoost();
m_vehicle->activateZipper(f);
MaxSpeed::increaseMaxSpeed(MS_INCREASE_ZIPPER, +10,
5.0f, 5.0f);
}
@@ -1267,33 +1290,8 @@ void Kart::updatePhysics(float dt)
if (forwardW.dot(getVehicle()->getRigidBody()->getLinearVelocity()) < btScalar(0.))
m_speed *= -1.f;
//cap at maximum velocity
float max_speed = getMaxSpeedOnTerrain();
if (m_zipper_time_left > 0.0f)
{
const float zipper_fade_time = 3.0f;
if (m_zipper_time_left > zipper_fade_time)
{
max_speed *= (1.0f + stk_config->m_zipper_max_speed_fraction);
}
else
{
max_speed *= (1.0f + (stk_config->m_zipper_max_speed_fraction * m_zipper_time_left * 1.0f/zipper_fade_time));
}
}
if ( m_speed > max_speed && isOnGround())
{
const float velocity_ratio = max_speed/m_speed;
m_speed = max_speed;
btVector3 velocity = m_body->getLinearVelocity();
velocity.setZ( velocity.getZ() * velocity_ratio );
velocity.setX( velocity.getX() * velocity_ratio );
velocity.setY( velocity.getY() * velocity_ratio ); // Up-down too
getVehicle()->getRigidBody()->setLinearVelocity( velocity );
}
// Cap speed if necessary
MaxSpeed::update(dt);
// To avoid tunneling (which can happen on long falls), clamp the
// velocity in Y direction. Tunneling can happen if the Y velocity
@@ -1322,6 +1320,7 @@ void Kart::updatePhysics(float dt)
{
if(isOnGround())
{
float max_speed = MaxSpeed::getCurrentMaxSpeed();
// Engine noise is based half in total speed, half in fake gears:
// With a sawtooth graph like /|/|/| we get 3 even spaced gears,
// ignoring the gear settings from stk_config, but providing a
@@ -1378,7 +1377,7 @@ void Kart::loadData()
m_smoke_system = new Smoke(this);
m_water_splash_system = new WaterSplash(this);
m_nitro = new Nitro(this);
m_slipstream = new SlipStream(this);
m_slipstream = new SlipStream(this);
if(m_kart_properties->hasSkidmarks())
m_skidmarks = new SkidMarks(*this);

View File

@@ -27,13 +27,13 @@
#include "items/attachment.hpp"
#include "items/powerup.hpp"
#include "karts/controller/controller.hpp"
#include "karts/controller/kart_control.hpp"
#include "karts/emergency_animation.hpp"
#include "karts/max_speed.hpp"
#include "karts/moveable.hpp"
#include "karts/kart_model.hpp"
#include "karts/kart_properties.hpp"
#include "karts/controller/controller.hpp"
#include "karts/controller/kart_control.hpp"
#include "karts/kart_model.hpp"
#include "tracks/terrain_info.hpp"
#include "utils/no_copy.hpp"
@@ -60,7 +60,8 @@ class WaterSplash;
* and TerrainInfo, which manages the terrain the kart is on.
* \ingroup karts
*/
class Kart : public TerrainInfo, public Moveable, public EmergencyAnimation
class Kart : public TerrainInfo, public Moveable, public EmergencyAnimation,
public MaxSpeed
{
private:
/** Reset position. */
@@ -93,7 +94,6 @@ private:
protected: // Used by the AI atm
KartControl m_controls; // The kart controls (e.g. steering, fire, ...)
Powerup m_powerup;
float m_zipper_time_left; /**<Zipper time left. */
Attachment *m_attachment;
/** Easier access for player_kart. */
Camera *m_camera;
@@ -229,6 +229,7 @@ public:
void resetBrakes ();
void startEngineSFX ();
void adjustSpeed (float f);
void capSpeed (float max_speed);
void updatedWeight ();
virtual void collectedItem (Item *item, int random_attachment);
virtual void reset ();
@@ -292,9 +293,6 @@ public:
/** Returns the number of powerups. */
int getNumPowerup () const { return m_powerup.getNum(); }
// ------------------------------------------------------------------------
/** Returns the time left for a zipper. */
float getZipperTimeLeft () const { return m_zipper_time_left; }
// ------------------------------------------------------------------------
/** Returns the remaining collected energy. */
float getEnergy () const { return m_collected_energy; }
// ------------------------------------------------------------------------

View File

@@ -75,6 +75,8 @@ KartProperties::KartProperties(const std::string &filename)
m_rubber_band_max_length = m_rubber_band_force =
m_rubber_band_duration = m_plunger_in_face_duration[0] =
m_plunger_in_face_duration[1] = m_plunger_in_face_duration[2] =
m_zipper_time = m_zipper_force = m_zipper_speed_gain =
m_zipper_max_speed_increase = m_zipper_fade_out_time =
m_time_till_max_skid =
m_skid_decrease = m_skid_increase = m_skid_visual = m_skid_max =
m_slipstream_length = m_slipstream_collect_time =
@@ -405,6 +407,15 @@ void KartProperties::getAllData(const XMLNode * root)
m_plunger_in_face_duration[2] = v[2];
}
if(const XMLNode *zipper_node= root->getNode("zipper"))
{
zipper_node->get("time", &m_zipper_time );
zipper_node->get("fade-out-time", &m_zipper_fade_out_time );
zipper_node->get("force", &m_zipper_force );
zipper_node->get("speed-gain", &m_zipper_speed_gain );
zipper_node->get("max-speed-increase", &m_zipper_max_speed_increase);
}
if(const XMLNode *camera_node= root->getNode("camera"))
{
camera_node->get("distance", &m_camera_distance);
@@ -522,11 +533,16 @@ void KartProperties::checkAllSet(const std::string &filename)
CHECK_NEG(m_upright_max_force, "upright max-force" );
CHECK_NEG(m_track_connection_accel, "track-connection-accel" );
CHECK_NEG(m_rubber_band_max_length, "rubber-band max-length" );
CHECK_NEG(m_plunger_in_face_duration[0],"plunger: in-face-time[0]" );
CHECK_NEG(m_plunger_in_face_duration[1],"plunger: in-face-time[1]" );
CHECK_NEG(m_plunger_in_face_duration[2],"plunger: in-face-time[2]" );
CHECK_NEG(m_plunger_in_face_duration[0],"plunger: in-face-time[0]" );
CHECK_NEG(m_plunger_in_face_duration[1],"plunger: in-face-time[1]" );
CHECK_NEG(m_plunger_in_face_duration[2],"plunger: in-face-time[2]" );
CHECK_NEG(m_rubber_band_force, "rubber-band force" );
CHECK_NEG(m_rubber_band_duration, "rubber-band duration" );
CHECK_NEG(m_zipper_time, "zipper-time" );
CHECK_NEG(m_zipper_fade_out_time, "zipper-fade-out-time" );
CHECK_NEG(m_zipper_force, "zipper-force" );
CHECK_NEG(m_zipper_speed_gain, "zipper-speed-gain" );
CHECK_NEG(m_zipper_max_speed_increase, "zipper-max-speed-increase" );
CHECK_NEG(m_skid_decrease, "skid decrease" );
CHECK_NEG(m_time_till_max_skid, "skid time-till-max" );
CHECK_NEG(m_skid_increase, "skid increase" );

View File

@@ -132,6 +132,21 @@ private:
/** How far away from an explosion karts will still be affected. */
float m_explosion_radius;
/** Duration a zipper is active. */
float m_zipper_time;
/** Fade out time for a zipper. */
float m_zipper_fade_out_time;
/** Additional force added to the acceleration. */
float m_zipper_force;
/** Initial one time speed gain. */
float m_zipper_speed_gain;
/** Absolute increase of the kart's maximum speed (in m/s). */
float m_zipper_max_speed_increase;
/** Vertical offset after rescue. */
float m_rescue_vert_offset;
@@ -403,6 +418,18 @@ public:
/** Returns duration of a plunger in your face. */
float getPlungerInFaceTime () const
{return m_plunger_in_face_duration[race_manager->getDifficulty()];}
/** Returns the time a zipper is active. */
float getZipperTime () const {return m_zipper_time; }
/** Returns the time a zipper is active. */
float getZipperFadeOutTime () const {return m_zipper_fade_out_time; }
/** Returns the additional force added applied to the kart. */
float getZipperForce () const { return m_zipper_force; }
/** Returns the initial zipper speed gain. */
float getZipperSpeedGain () const { return m_zipper_speed_gain; }
/** Returns the increase of the maximum speed of the kart
* if a zipper is active. */
float getZipperMaxSpeedIncrease () const { return m_zipper_max_speed_increase;}
/** Returns additional rotation of 3d model when skidding. */
float getSkidVisual () const {return m_skid_visual; }

176
src/karts/max_speed.cpp Normal file
View File

@@ -0,0 +1,176 @@
// $Id: max_speed.cpp 6306 2010-10-18 06:04:05Z hikerstk $
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2010 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/max_speed.hpp"
#include <algorithm>
#include <assert.h>
#include "karts/kart.hpp"
/** This class handles maximum speed for karts. Several factors can influence
* the maximum speed a kart can drive, some will decrease the maximum speed,
* some will increase the maximum speed.
* Slowdowns are specified in fraction of the (kart specific) maximum speed
* of that kart. The following categories are defined:
* - terrain-specific slow downs
* - AI related slow down (low level AIs might drive slower than player)
* - end controller related AI (end controller drives slower)
* The largest slowdown of all those factors is applied to the maximum
* speed of the kart.
* Increase of maximum speed is given absolute, i.e. in m/s. The following
* circumstances can increase the maximum speed:
* - Use of a zipper
* - Use of sliptstream
* - Use of nitro
* The speed increases for all those are added after applying the maximum
* slowdown fraction.
* At the end the maximum is capped by a value specified in stk_config
* (to avoid issues with physics etc).
*/
MaxSpeed::MaxSpeed(Kart *kart)
{
m_kart = kart;
} // MaxSpeed
// ----------------------------------------------------------------------------
/** Reset to prepare for a restart. It just overwrites each entry with a
* newly constructed values, i.e. values that don't cause any slowdown
* or speedup.
*/
void MaxSpeed::reset()
{
m_current_max_speed = m_kart->getKartProperties()->getMaxSpeed();
for(unsigned int i=MS_DECREASE_MIN; i<MS_DECREASE_MAX; i++)
{
SpeedDecrease sd;
m_speed_decrease[i] = sd;
}
// Then add the speed increase from each category
// ----------------------------------------------
for(unsigned int i=MS_INCREASE_MIN; i<MS_INCREASE_MAX; i++)
{
SpeedIncrease si;
m_speed_increase[i] = si;
}
} // reset
// ----------------------------------------------------------------------------
/** Sets an increased maximum speed for a category.
* \param category The category for which to set the higher maximum speed.
* \param add_speed How much speed (in m/s) is added to the maximum speed.
* \param duration How long the speed increase will last.
* \param fade_out_time How long the maximum speed will fade out linearly.
*/
void MaxSpeed::increaseMaxSpeed(unsigned int category, float add_speed,
float duration, float fade_out_time)
{
assert(category>=MS_INCREASE_MIN && category <MS_INCREASE_MAX);
m_speed_increase[category].m_duration = duration;
m_speed_increase[category].m_fade_out_time = fade_out_time;
m_speed_increase[category].m_max_add_speed = add_speed;
m_speed_increase[category].m_current_speedup = add_speed;
} // increaseMaxSpeed
// ----------------------------------------------------------------------------
/** Handles the update of speed increase objects. The m_duration variable
* contains the remaining time - as long as this variable is positibe,
* the maximum speed increase applies, while when it is between
* -m_fade_out_time and 0, the maximum speed will linearly decrease.
* \param dt Time step size.
*/
void MaxSpeed::SpeedIncrease::update(float dt)
{
m_duration -= dt;
// ENd of increased max speed reached.
if(m_duration < -m_fade_out_time)
{
m_current_speedup = 0;
return;
}
// If we are still in main max speed increase time, do nothing
if(m_duration >0) return;
// Now we are in the fade out period: decrease time linearly
m_current_speedup -= dt*m_max_add_speed/m_fade_out_time;
} // SpeedIncrease::update
// ----------------------------------------------------------------------------
void MaxSpeed::setSlowdown(unsigned int category, float max_speed_fraction,
float fade_in_time)
{
assert(category>=MS_DECREASE_MIN && category <MS_DECREASE_MAX);
m_speed_decrease[category].m_max_speed_fraction = max_speed_fraction;
m_speed_decrease[category].m_fade_in_time = fade_in_time;
} // setSlowdown
// ----------------------------------------------------------------------------
void MaxSpeed::SpeedDecrease::update(float dt)
{
float diff = m_current_fraction - m_max_speed_fraction;
if(diff > 0)
{
if (diff * m_fade_in_time > dt)
m_current_fraction -= dt/m_fade_in_time;
else
m_current_fraction = m_max_speed_fraction;
}
else
m_current_fraction = m_max_speed_fraction;
} // SpeedDecrease::update
// ----------------------------------------------------------------------------
float MaxSpeed::getSpeedIncreaseTimeLeft(unsigned int category)
{
return m_speed_increase[category].getTimeLeft();
} // getSpeedIncreaseTimeLeft
// ----------------------------------------------------------------------------
void MaxSpeed::update(float dt)
{
// First comput the minimum max-speed fraction, which
// determines the overall decrease of maximum speed.
// ---------------------------------------------------
float f = 1.0f;
for(unsigned int i=MS_DECREASE_MIN; i<MS_DECREASE_MAX; i++)
{
SpeedDecrease &slowdown = m_speed_decrease[i];
slowdown.update(dt);
f = std::min(f, slowdown.getSlowdownFraction());
}
m_current_max_speed = m_kart->getKartProperties()->getMaxSpeed() * f;
// Then add the speed increase from each category
// ----------------------------------------------
for(unsigned int i=MS_INCREASE_MIN; i<MS_INCREASE_MAX; i++)
{
SpeedIncrease &speedup = m_speed_increase[i];
speedup.update(dt);
m_current_max_speed += speedup.getSpeedIncrease();
}
// Then cap the current speed of the kart
// --------------------------------------
m_kart->capSpeed(m_current_max_speed);
} // update
// ----------------------------------------------------------------------------

138
src/karts/max_speed.hpp Normal file
View File

@@ -0,0 +1,138 @@
// $Id: max_speed.hpp 6307 2010-10-18 11:08:22Z hikerstk $
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2010 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_MAX_SPEED_HPP
#define HEADER_MAX_SPEED_HPP
/** \defgroup karts */
class Kart;
class MaxSpeed
{
public:
/** The categories to use for increasing the speed of a kart:
* Increase due to zipper, slipstream, nitro usage. */
enum {MS_INCREASE_MIN,
MS_INCREASE_ZIPPER = MS_INCREASE_MIN,
MS_INCREASE_SLIPSTREAM,
MS_INCREASE_NITRO,
MS_INCREASE_MAX};
/** The categories to use for decreasing the speed of a kart:
* Decrease due to terrain, different AI levels and end controller. */
enum {MS_DECREASE_MIN,
MS_DECREASE_TERRAIN = MS_DECREASE_MIN,
MS_DECREASE_AI,
MS_DECREASE_MAX};
private:
/** A pointer to the kart to which this speed handling object belongs. */
Kart *m_kart;
/** The current maximum speed. */
float m_current_max_speed;
// ------------------------------------------------------------------------
/** An internal class to store and handle speed increase related data. */
class SpeedIncrease
{
public:
/** The maximum additional speed allowed. */
float m_max_add_speed;
/** How long this speed will apply. This is used as a timer internally,
* to the duration will be decreased. When the duration is <0, the
* fade out time starts, and duration will go down to
* -m_fade_out_time before this speed increase stops. */
float m_duration;
/** The fadeout time. */
float m_fade_out_time;
/** The current max speed increase value. */
float m_current_speedup;
/** The constructor initialised the values with a no-increase
* entry, i.e. an entry that does affect top speed at all. */
SpeedIncrease()
{
m_max_add_speed = 0;
m_duration = -9999999;
m_fade_out_time = 0;
m_current_speedup = 0;
} // SpeedIncrease
void update(float dt);
/** Returns the current speedup for this category. */
float getSpeedIncrease() const {return m_current_speedup;}
/** Returns the remaining time till the fade out time starts.
* Note that this function will return a negative value if
* the fade_out time has started or this speed increase has
* expired. */
float getTimeLeft() const {return m_duration; }
}; // SpeedIncrease
// ------------------------------------------------------------------------
/** An internal class to store and handle speed decrease related data. */
class SpeedDecrease
{
public:
/** The maximum slowdown to apply. */
float m_max_speed_fraction;
/** How long it should take for the full slowdown to take effect. */
float m_fade_in_time;
/** The current slowdown fraction, taking the fade-in time
* into account. */
float m_current_fraction;
/** The constructor initialises the data with data that won't
* affect top speed at all. */
SpeedDecrease()
{
m_max_speed_fraction = 1.0f;
m_fade_in_time = 0.0f;
m_current_fraction = 1.0f;
} // SpeedDecrease
void update(float dt);
/** Returns the current slowdown fracftion, taking a 'fade in'
* into account. */
float getSlowdownFraction() const {return m_current_fraction;}
}; // SpeedDecrease
// ------------------------------------------------------------------------
/** Stores all speed decrease related information
* for each possible category. */
SpeedDecrease m_speed_decrease[MS_DECREASE_MAX];
/** Stores all speed increase related information
* for each possible category. */
SpeedIncrease m_speed_increase[MS_INCREASE_MAX];
public:
MaxSpeed(Kart *kart);
void increaseMaxSpeed(unsigned int category, float add_speed,
float duration, float fade_out_time);
void setSlowdown(unsigned int category, float max_speed_fraction,
float fade_in_time);
float getSpeedIncreaseTimeLeft(unsigned int category);
void update(float dt);
void reset();
/** Returns the current maximum speed for this kart. */
float getCurrentMaxSpeed() const { return m_current_max_speed; }
}; // MaxSpeed
#endif