Refactoring: interpolating values is now handled in a separate class

InterpolationArray. This class is now used for the skidding probability
of the AI and the turn radius of all karts (which depends on speed).


git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@11689 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hikerstk 2012-10-16 05:51:46 +00:00
parent 4f7f1379df
commit fbb9e5f8d2
10 changed files with 284 additions and 205 deletions

View File

@ -280,11 +280,11 @@
<swatter duration="10" distance="3" squash-duration="5" <swatter duration="10" distance="3" squash-duration="5"
squash-slowdown="0.5"/> squash-slowdown="0.5"/>
<!-- turn-speed and turn-radius define the turn radius of the kart at <!-- turn-radius defines the turn radius of the kart at
the given speed. The actual steering angle is dependent on the a given speed. The actual steering angle is dependent on the
wheel base of the kart: radius = wheel_base/sin(steering_angle). wheel base of the kart: radius = wheel_base/sin(steering_angle).
The values below define that at speed 0 the turn radius is 3, at The values below define that at speed 0 the turn radius is 2, at
speed 10 (and up to 25 then) the radius is 15 etc. speed 10 the radius is 7.5 etc.
The actual turn radius is piece-wise linearly interpolated. This The actual turn radius is piece-wise linearly interpolated. This
allows for tighter turning at lower speeds, and also avoids that allows for tighter turning at lower speeds, and also avoids that
the kart becomes too hard to control at high speed (speeds of higher the kart becomes too hard to control at high speed (speeds of higher
@ -292,8 +292,7 @@
time-full-steer is the time when a player's input goes from neutral time-full-steer is the time when a player's input goes from neutral
steering to extreme left or right. steering to extreme left or right.
--> -->
<turn turn-speed= "0 10 25 45" <turn turn-radius="0:2.0 10:7.5 25:15 45:25"
turn-radius="2.0 7.5 15 25"
time-full-steer ="0.2" /> time-full-steer ="0.2" />
<!-- Speed and acceleration related values: power and max-speed (in m/s) <!-- Speed and acceleration related values: power and max-speed (in m/s)

View File

@ -95,8 +95,8 @@ src/items/projectile_manager.cpp
src/items/rubber_ball.cpp src/items/rubber_ball.cpp
src/items/rubber_band.cpp src/items/rubber_band.cpp
src/items/swatter.cpp src/items/swatter.cpp
src/karts/abstract_kart_animation.cpp
src/karts/abstract_kart.cpp src/karts/abstract_kart.cpp
src/karts/abstract_kart_animation.cpp
src/karts/cannon_animation.cpp src/karts/cannon_animation.cpp
src/karts/controller/ai_base_controller.cpp src/karts/controller/ai_base_controller.cpp
src/karts/controller/ai_properties.cpp src/karts/controller/ai_properties.cpp
@ -188,13 +188,13 @@ src/states_screens/kart_selection.cpp
src/states_screens/main_menu_screen.cpp src/states_screens/main_menu_screen.cpp
src/states_screens/minimal_race_gui.cpp src/states_screens/minimal_race_gui.cpp
src/states_screens/options_screen_audio.cpp src/states_screens/options_screen_audio.cpp
src/states_screens/options_screen_input2.cpp
src/states_screens/options_screen_input.cpp src/states_screens/options_screen_input.cpp
src/states_screens/options_screen_input2.cpp
src/states_screens/options_screen_players.cpp src/states_screens/options_screen_players.cpp
src/states_screens/options_screen_ui.cpp src/states_screens/options_screen_ui.cpp
src/states_screens/options_screen_video.cpp src/states_screens/options_screen_video.cpp
src/states_screens/race_gui_base.cpp
src/states_screens/race_gui.cpp src/states_screens/race_gui.cpp
src/states_screens/race_gui_base.cpp
src/states_screens/race_gui_overworld.cpp src/states_screens/race_gui_overworld.cpp
src/states_screens/race_result_gui.cpp src/states_screens/race_result_gui.cpp
src/states_screens/race_setup_screen.cpp src/states_screens/race_setup_screen.cpp
@ -255,8 +255,8 @@ src/animations/billboard_animation.hpp
src/animations/ipo.hpp src/animations/ipo.hpp
src/animations/three_d_animation.hpp src/animations/three_d_animation.hpp
src/audio/dummy_sfx.hpp src/audio/dummy_sfx.hpp
src/audio/music_dummy.hpp
src/audio/music.hpp src/audio/music.hpp
src/audio/music_dummy.hpp
src/audio/music_information.hpp src/audio/music_information.hpp
src/audio/music_manager.hpp src/audio/music_manager.hpp
src/audio/music_ogg.hpp src/audio/music_ogg.hpp
@ -264,8 +264,8 @@ src/audio/sfx_base.hpp
src/audio/sfx_buffer.hpp src/audio/sfx_buffer.hpp
src/audio/sfx_manager.hpp src/audio/sfx_manager.hpp
src/audio/sfx_openal.hpp src/audio/sfx_openal.hpp
src/challenges/challenge_data.hpp
src/challenges/challenge.hpp src/challenges/challenge.hpp
src/challenges/challenge_data.hpp
src/challenges/game_slot.hpp src/challenges/game_slot.hpp
src/challenges/unlock_manager.hpp src/challenges/unlock_manager.hpp
src/config/device_config.hpp src/config/device_config.hpp
@ -306,11 +306,11 @@ src/guiengine/scalable_font.hpp
src/guiengine/screen.hpp src/guiengine/screen.hpp
src/guiengine/skin.hpp src/guiengine/skin.hpp
src/guiengine/widget.hpp src/guiengine/widget.hpp
src/guiengine/widgets.hpp
src/guiengine/widgets/bubble_widget.hpp src/guiengine/widgets/bubble_widget.hpp
src/guiengine/widgets/button_widget.hpp src/guiengine/widgets/button_widget.hpp
src/guiengine/widgets/check_box_widget.hpp src/guiengine/widgets/check_box_widget.hpp
src/guiengine/widgets/dynamic_ribbon_widget.hpp src/guiengine/widgets/dynamic_ribbon_widget.hpp
src/guiengine/widgets.hpp
src/guiengine/widgets/icon_button_widget.hpp src/guiengine/widgets/icon_button_widget.hpp
src/guiengine/widgets/label_widget.hpp src/guiengine/widgets/label_widget.hpp
src/guiengine/widgets/list_widget.hpp src/guiengine/widgets/list_widget.hpp
@ -321,8 +321,8 @@ src/guiengine/widgets/spinner_widget.hpp
src/guiengine/widgets/text_box_widget.hpp src/guiengine/widgets/text_box_widget.hpp
src/input/binding.hpp src/input/binding.hpp
src/input/device_manager.hpp src/input/device_manager.hpp
src/input/input_device.hpp
src/input/input.hpp src/input/input.hpp
src/input/input_device.hpp
src/input/input_manager.hpp src/input/input_manager.hpp
src/input/wiimote_manager.hpp src/input/wiimote_manager.hpp
src/io/file_manager.hpp src/io/file_manager.hpp
@ -343,8 +343,8 @@ src/items/projectile_manager.hpp
src/items/rubber_ball.hpp src/items/rubber_ball.hpp
src/items/rubber_band.hpp src/items/rubber_band.hpp
src/items/swatter.hpp src/items/swatter.hpp
src/karts/abstract_kart_animation.hpp
src/karts/abstract_kart.hpp src/karts/abstract_kart.hpp
src/karts/abstract_kart_animation.hpp
src/karts/cannon_animation.hpp src/karts/cannon_animation.hpp
src/karts/controller/ai_base_controller.hpp src/karts/controller/ai_base_controller.hpp
src/karts/controller/ai_properties.hpp src/karts/controller/ai_properties.hpp
@ -357,8 +357,8 @@ src/karts/controller/present_ai.hpp
src/karts/controller/skidding_ai.hpp src/karts/controller/skidding_ai.hpp
src/karts/explosion_animation.hpp src/karts/explosion_animation.hpp
src/karts/ghost_kart.hpp src/karts/ghost_kart.hpp
src/karts/kart_gfx.hpp
src/karts/kart.hpp src/karts/kart.hpp
src/karts/kart_gfx.hpp
src/karts/kart_model.hpp src/karts/kart_model.hpp
src/karts/kart_properties.hpp src/karts/kart_properties.hpp
src/karts/kart_properties_manager.hpp src/karts/kart_properties_manager.hpp
@ -449,13 +449,13 @@ src/states_screens/kart_selection.hpp
src/states_screens/main_menu_screen.hpp src/states_screens/main_menu_screen.hpp
src/states_screens/minimal_race_gui.hpp src/states_screens/minimal_race_gui.hpp
src/states_screens/options_screen_audio.hpp src/states_screens/options_screen_audio.hpp
src/states_screens/options_screen_input2.hpp
src/states_screens/options_screen_input.hpp src/states_screens/options_screen_input.hpp
src/states_screens/options_screen_input2.hpp
src/states_screens/options_screen_players.hpp src/states_screens/options_screen_players.hpp
src/states_screens/options_screen_ui.hpp src/states_screens/options_screen_ui.hpp
src/states_screens/options_screen_video.hpp src/states_screens/options_screen_video.hpp
src/states_screens/race_gui_base.hpp
src/states_screens/race_gui.hpp src/states_screens/race_gui.hpp
src/states_screens/race_gui_base.hpp
src/states_screens/race_gui_overworld.hpp src/states_screens/race_gui_overworld.hpp
src/states_screens/race_result_gui.hpp src/states_screens/race_result_gui.hpp
src/states_screens/race_setup_screen.hpp src/states_screens/race_setup_screen.hpp
@ -484,8 +484,8 @@ src/tracks/check_sphere.hpp
src/tracks/check_structure.hpp src/tracks/check_structure.hpp
src/tracks/graph_node.hpp src/tracks/graph_node.hpp
src/tracks/lod_node_loader.hpp src/tracks/lod_node_loader.hpp
src/tracks/quad_graph.hpp
src/tracks/quad.hpp src/tracks/quad.hpp
src/tracks/quad_graph.hpp
src/tracks/quad_set.hpp src/tracks/quad_set.hpp
src/tracks/terrain_info.hpp src/tracks/terrain_info.hpp
src/tracks/track.hpp src/tracks/track.hpp
@ -493,11 +493,12 @@ src/tracks/track_manager.hpp
src/tracks/track_object.hpp src/tracks/track_object.hpp
src/tracks/track_object_manager.hpp src/tracks/track_object_manager.hpp
src/tracks/track_sector.hpp src/tracks/track_sector.hpp
src/tutorial/tutorial_data.hpp
src/tutorial/tutorial.hpp src/tutorial/tutorial.hpp
src/tutorial/tutorial_data.hpp
src/tutorial/tutorial_manager.hpp src/tutorial/tutorial_manager.hpp
src/utils/aligned_array.hpp src/utils/aligned_array.hpp
src/utils/constants.hpp src/utils/constants.hpp
src/utils/interpolation_array.hpp
src/utils/leak_check.hpp src/utils/leak_check.hpp
src/utils/no_copy.hpp src/utils/no_copy.hpp
src/utils/profiler.hpp src/utils/profiler.hpp

View File

@ -1774,6 +1774,10 @@
RelativePath="..\..\utils\cpp2011.h" RelativePath="..\..\utils\cpp2011.h"
> >
</File> </File>
<File
RelativePath="..\..\utils\interpolation_array.hpp"
>
</File>
<File <File
RelativePath="..\..\utils\leak_check.hpp" RelativePath="..\..\utils\leak_check.hpp"
> >

View File

@ -19,6 +19,7 @@
#include "io/file_manager.hpp" #include "io/file_manager.hpp"
#include "io/xml_node.hpp" #include "io/xml_node.hpp"
#include "utils/string_utils.hpp" #include "utils/string_utils.hpp"
#include "utils/interpolation_array.hpp"
#include "utils/vec3.hpp" #include "utils/vec3.hpp"
#include <stdexcept> #include <stdexcept>
@ -442,6 +443,53 @@ int XMLNode::get(const std::string &attribute, std::vector<int> *value) const
return value->size(); return value->size();
} // get(vector<int>) } // get(vector<int>)
// ----------------------------------------------------------------------------
/** Reads an InterpolatioARray. The values must be specified as:
* x0:y0 x1:y1 x2:y2 ...
* and the X values must be sorted. The function will abort (exit) with
* an error message in case of incorrectly formed x:y pairs.
* \param attribute Name of the attribute.
* \param value The InterpolationArray.
* \returns 0 in case of an error, !=0 otherwise
*/
int XMLNode::get(const std::string &attribute, InterpolationArray *value) const
{
std::string s;
if(!get(attribute, &s)) return 0;
std::vector<std::string> pairs = StringUtils::split(s, ' ');
for(unsigned int i=0; i<pairs.size(); i++)
{
std::vector<std::string> pair = StringUtils::split(pairs[i],':');
if(pair.size()!=2)
{
printf("Incorrect interpolation pair '%s' in '%s'.\n",
pairs[i].c_str(), attribute.c_str());
printf("Must be x:y.\n");
exit(-1);
}
float x;
if(!StringUtils::fromString(pair[0], x))
{
printf("Incorrect x in pair '%s' of '%s'.\n",
pairs[i].c_str(), attribute.c_str());
exit(-1);
}
float y;
if(!StringUtils::fromString(pair[1], y))
{
printf("Incorrect y in pair '%s' in '%s'.\n",
pair[1].c_str(), attribute.c_str());
exit(-1);
}
if(!value->push_back(x, y))
{
return 0;
}
} // for i
return 1;
} // get(InterpolationArray)
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
/** Interprets the attributes 'x', 'y', 'z' or 'h', 'p', 'r' as a 3d vector /** Interprets the attributes 'x', 'y', 'z' or 'h', 'p', 'r' as a 3d vector
* and set the corresponding elements of value. Not all values need to be * and set the corresponding elements of value. Not all values need to be

View File

@ -44,6 +44,7 @@ using namespace irr;
#include "utils/no_copy.hpp" #include "utils/no_copy.hpp"
#include "utils/time.hpp" #include "utils/time.hpp"
class InterpolationArray;
class Vec3; class Vec3;
/** /**
@ -93,6 +94,7 @@ public:
int get(const std::string &attribute, std::vector<std::string> *value) const; int get(const std::string &attribute, std::vector<std::string> *value) const;
int get(const std::string &attribute, std::vector<float> *value) const; int get(const std::string &attribute, std::vector<float> *value) const;
int get(const std::string &attribute, std::vector<int> *value) const; int get(const std::string &attribute, std::vector<int> *value) const;
int get(const std::string &attribute, InterpolationArray *value) const;
int get(core::vector3df *value) const; int get(core::vector3df *value) const;
int getXYZ(core::vector3df *value) const; int getXYZ(core::vector3df *value) const;
int getXYZ(Vec3 *vaslue) const; int getXYZ(Vec3 *vaslue) const;

View File

@ -26,6 +26,7 @@ float AIProperties::UNDEFINED = -99.9f;
/** Constructor. Sets all properties to the special UNDEFINED value. /** Constructor. Sets all properties to the special UNDEFINED value.
*/ */
AIProperties::AIProperties() AIProperties::AIProperties()
: m_skid_probability(/*decreasing*/false)
{ {
m_max_item_angle = UNDEFINED; m_max_item_angle = UNDEFINED;
m_max_item_angle_high_speed = UNDEFINED; m_max_item_angle_high_speed = UNDEFINED;
@ -45,51 +46,14 @@ void AIProperties::load(const XMLNode *ai_node)
ai_node->get("time-full-steer", &m_time_full_steer ); ai_node->get("time-full-steer", &m_time_full_steer );
ai_node->get("bad-item-closeness", &m_bad_item_closeness_2 ); ai_node->get("bad-item-closeness", &m_bad_item_closeness_2 );
ai_node->get("straight-length-for-zipper",&m_straight_length_for_zipper); ai_node->get("straight-length-for-zipper",&m_straight_length_for_zipper);
ai_node->get("rb-skid-probability", &m_skid_probability );
std::string s; if(m_skid_probability.size()==0)
ai_node->get("rb-skid-probability", &s);
std::vector<std::string> pairs = StringUtils::split(s, ' ');
for(unsigned int i=0; i<pairs.size(); i++)
{
std::vector<std::string> pair = StringUtils::split(pairs[i],':');
if(pair.size()!=2)
{
printf("Incorrect pair '%s' in rd-skid-probability.\n",
pairs[i].c_str());
printf("Must be distance:probability.\n");
exit(-1);
}
float distance;
if(!StringUtils::fromString(pair[0], distance))
{
printf("Incorrect distance in pair '%s'.\n", pairs[i].c_str());
exit(-1);
}
float p;
if(!StringUtils::fromString(pair[1], p))
{
printf(
"Incorrect probability in pair '%s' in rb-skid-probability.\n",
pair[1].c_str());
exit(-1);
}
m_skid_distances.push_back(distance);
m_skid_probabilities.push_back(p);
} // for i
if(m_skid_distances.size()==0)
{ {
printf("No skid probability defined.\n"); printf("No skid probability defined.\n");
exit(-1); exit(-1);
} }
for(unsigned int i=0; i<m_skid_distances.size()-1; i++)
{
if(m_skid_distances[i]>=m_skid_distances[i+1])
{
printf("Skid distances must be sorted.\n");
exit(-1);
}
}
// We actually need the square of the distance later // We actually need the square of the distance later
m_bad_item_closeness_2 *= m_bad_item_closeness_2; m_bad_item_closeness_2 *= m_bad_item_closeness_2;
@ -120,30 +84,4 @@ void AIProperties::copyFrom(const AIProperties *destination)
*this = *destination; *this = *destination;
} // copyFrom } // copyFrom
// ----------------------------------------------------------------------------
float AIProperties::getSkiddingProbability(float distance) const
{
if(m_skid_distances.size()==1)
return m_skid_probabilities[0];
if(distance<m_skid_distances[0])
return m_skid_probabilities[0];
if(distance>m_skid_distances[m_skid_distances.size()-1])
return m_skid_probabilities[m_skid_probabilities.size()-1];
// Now distance must be between two of the distances in the
// sorted m_skid_distances array
for(unsigned int i=1; i<m_skid_distances.size(); i++)
{
if(distance >m_skid_distances[i]) continue;
float f = m_skid_probabilities[i-1] +
(m_skid_probabilities[i]-m_skid_probabilities[i-1]) *
(distance - m_skid_distances[i-1])/
(m_skid_distances[i]-m_skid_distances[i-1]);
return f;
}
assert(false);
return 0.0f;
} // getSkiddingProbability
/* EOF */ /* EOF */

View File

@ -19,6 +19,8 @@
#ifndef HEADER_AI_PROPERTIES_HPP #ifndef HEADER_AI_PROPERTIES_HPP
#define HEADER_AI_PROPERTIES_HPP #define HEADER_AI_PROPERTIES_HPP
#include "utils/interpolation_array.hpp"
#include <string> #include <string>
#include <vector> #include <vector>
@ -68,19 +70,21 @@ protected:
/** Minimum length of a straight in order to activate a zipper. */ /** Minimum length of a straight in order to activate a zipper. */
float m_straight_length_for_zipper; float m_straight_length_for_zipper;
/** The distances at which the skid probability is specified. */ /** The array of (distance, skid_probability) points. */
std::vector<float> m_skid_distances; InterpolationArray m_skid_probability;
/** The skidding probability depending on distance, which is stored
* in m_skid_distances - the two fields must have the same length. */
std::vector<float> m_skid_probabilities;
public: public:
AIProperties(); AIProperties();
void load(const XMLNode *skid_node); void load(const XMLNode *skid_node);
void copyFrom(const AIProperties *destination); void copyFrom(const AIProperties *destination);
void checkAllSet(const std::string &filename) const; void checkAllSet(const std::string &filename) const;
float getSkiddingProbability(float distance) const; // ------------------------------------------------------------------------
/** Returns the skidding probability dependent on the specified distance
* to the first player kart. */
float getSkiddingProbability(float distance) const
{
return m_skid_probability.get(distance);
} // getSkiddingProbability
}; // AIProperties }; // AIProperties

View File

@ -44,6 +44,7 @@ float KartProperties::UNDEFINED = -99.9f;
* defined, it is guaranteed that each kart has well defined physics values). * defined, it is guaranteed that each kart has well defined physics values).
*/ */
KartProperties::KartProperties(const std::string &filename) KartProperties::KartProperties(const std::string &filename)
: m_turn_angle_at_speed(/*decreasing*/true)
{ {
m_icon_material = NULL; m_icon_material = NULL;
m_minimap_icon = NULL; m_minimap_icon = NULL;
@ -56,10 +57,6 @@ KartProperties::KartProperties(const std::string &filename)
m_shadow_y_offset = 0.0f; m_shadow_y_offset = 0.0f;
m_groups.clear(); m_groups.clear();
m_turn_angle_at_speed.clear();
m_turn_radius_at_speed.clear();
m_turn_speed.clear();
m_speed_angle_increase.clear();
m_custom_sfx_id.resize(SFXManager::NUM_CUSTOMS); m_custom_sfx_id.resize(SFXManager::NUM_CUSTOMS);
// Set all other values to undefined, so that it can later be tested // Set all other values to undefined, so that it can later be tested
@ -242,20 +239,12 @@ void KartProperties::load(const std::string &filename, const std::string &node)
m_wheel_radius ); m_wheel_radius );
m_wheel_base = fabsf( m_kart_model->getWheelPhysicsPosition(0).getZ() m_wheel_base = fabsf( m_kart_model->getWheelPhysicsPosition(0).getZ()
-m_kart_model->getWheelPhysicsPosition(2).getZ()); -m_kart_model->getWheelPhysicsPosition(2).getZ());
for(unsigned int i=0; i<m_turn_radius_at_speed.size(); i++)
// Now convert the turn radius into turn angle:
for(unsigned int i=0; i<m_turn_angle_at_speed.size(); i++)
{ {
m_turn_angle_at_speed.push_back( m_turn_angle_at_speed.setY( i,
sin(m_wheel_base/m_turn_radius_at_speed[i]) sin(m_wheel_base/m_turn_angle_at_speed.getY(i)) );
);
}
for(unsigned int i=0; i<m_turn_speed.size()-1; i++)
{
if(m_turn_speed[i]==m_turn_speed[i+1])
m_speed_angle_increase.push_back(0);
else
m_speed_angle_increase.push_back(
(m_turn_angle_at_speed[i]-m_turn_angle_at_speed[i+1])/
(m_turn_speed[i+1]-m_turn_speed[i]) );
} }
m_shadow_texture = irr_driver->getTexture(m_shadow_file); m_shadow_texture = irr_driver->getTexture(m_shadow_file);
@ -347,33 +336,10 @@ void KartProperties::getAllData(const XMLNode * root)
if(const XMLNode *turn_node = root->getNode("turn")) if(const XMLNode *turn_node = root->getNode("turn"))
{ {
turn_node->get("time-full-steer", &m_time_full_steer ); turn_node->get("time-full-steer", &m_time_full_steer );
turn_node->get("turn-speed", &m_turn_speed ); turn_node->get("turn-radius", &m_turn_angle_at_speed );
turn_node->get("turn-radius", &m_turn_radius_at_speed);
// For now store the turn radius in turn angle, the correct // For now store the turn radius in turn angle, the correct
// value can only be determined later in ::load // value can only be determined later in ::load
if(m_turn_speed.size()==0 ||
m_turn_radius_at_speed.size() != m_turn_speed.size())
{
printf("Inconsistent turn-speed and turn-radius "
"settings for kart %s\n", getIdent().c_str());
exit(-1);
} }
for(unsigned int i=0; i<m_turn_speed.size()-1; i++)
{
if(m_turn_speed[i]>m_turn_speed[i+1])
{
printf("The turn-speed must be specified with increasing "
"values for kart %s.\n", getIdent().c_str());
exit(-1);
}
if(m_turn_radius_at_speed[i]>m_turn_radius_at_speed[i+1])
{
printf("The turn-radius must be increasing for kart %s.\n",
getIdent().c_str());
exit(-1);
}
}
} // if turn_node
if(const XMLNode *engine_node = root->getNode("engine")) if(const XMLNode *engine_node = root->getNode("engine"))
{ {
@ -465,7 +431,8 @@ void KartProperties::getAllData(const XMLNode * root)
collision_node->get("bevel-factor", &m_bevel_factor ); collision_node->get("bevel-factor", &m_bevel_factor );
} }
//TODO: wheel front right and wheel front left is not loaded, yet is listed as an attribute in the xml file after wheel-radius //TODO: wheel front right and wheel front left is not loaded, yet is
//TODO: listed as an attribute in the xml file after wheel-radius
//TODO: same goes for their rear equivalents //TODO: same goes for their rear equivalents
if(const XMLNode *plunger_node= root->getNode("plunger")) if(const XMLNode *plunger_node= root->getNode("plunger"))
@ -685,50 +652,6 @@ void KartProperties::checkAllSet(const std::string &filename)
m_ai_properties->checkAllSet(filename); m_ai_properties->checkAllSet(filename);
} // checkAllSet } // checkAllSet
// ----------------------------------------------------------------------------
float KartProperties::getMaxSteerAngle(float speed) const
{
if(speed<=m_turn_speed[0]) return m_turn_angle_at_speed[0];
unsigned int last = m_turn_speed.size()-1;
if(speed>=m_turn_speed[last]) return m_turn_angle_at_speed[last];
for(unsigned int i=1; i<=last; i++)
{
if(speed <= m_turn_speed[i])
{
// Interpolate between i and i+1
return m_turn_angle_at_speed[i] -
(speed-m_turn_speed[i])*m_speed_angle_increase[i-1];
}
}
// This should never be reached
assert (0);
return 0; // avoid compiler warning
} // getMaxSteerAngle
// ----------------------------------------------------------------------------
/** Returns the (maximum) speed for a given turn radius.
* \param radius The radius for which the speed needs to be computed.
*/
float KartProperties::getSpeedForTurnRadius(float radius) const
{
if(radius < m_turn_radius_at_speed[0] )
return m_turn_speed[0];
const unsigned int last = m_turn_speed.size();
for(unsigned int i=1; i<last; i++)
{
if(radius < m_turn_radius_at_speed[i])
{
return m_turn_speed[i-1]
+ (m_turn_speed[i]-m_turn_speed[i-1]) * (radius-m_turn_radius_at_speed[i-1])
/ (m_turn_radius_at_speed[i]-m_turn_radius_at_speed[i-1]);
}
} // for i < last
return m_turn_speed[last-1];
} // getSpeedForTurnRadius
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
/** Called the first time a kart accelerates after 'ready-set-go'. It searches /** Called the first time a kart accelerates after 'ready-set-go'. It searches
* through m_startup_times to find the appropriate slot, and returns the * through m_startup_times to find the appropriate slot, and returns the

View File

@ -34,6 +34,7 @@ using namespace irr;
#include "karts/kart_model.hpp" #include "karts/kart_model.hpp"
#include "io/xml_node.hpp" #include "io/xml_node.hpp"
#include "race/race_manager.hpp" #include "race/race_manager.hpp"
#include "utils/interpolation_array.hpp"
#include "utils/vec3.hpp" #include "utils/vec3.hpp"
class AIProperties; class AIProperties;
@ -124,17 +125,9 @@ private:
* braking force. */ * braking force. */
float m_time_full_steer; /**< Time for player karts to reach full float m_time_full_steer; /**< Time for player karts to reach full
* steer angle. */ * steer angle. */
/** Stores the speeds at which the turn angle changes. */
std::vector<float> m_turn_speed;
/** Stores the turn angle at the corresponding turn speed. */ /** The turn angle depending on speed. */
std::vector<float> m_turn_angle_at_speed; InterpolationArray m_turn_angle_at_speed;
/** Stores the turn radius at the corresponding turn speed. */
std::vector<float> m_turn_radius_at_speed;
/** Increase of turn angle with speed. */
std::vector<float> m_speed_angle_increase;
/** If != 0 a bevelled box shape is used by using a point cloud as a /** If != 0 a bevelled box shape is used by using a point cloud as a
* collision shape. */ * collision shape. */
@ -300,13 +293,16 @@ private:
/** How long the slip stream speed increase will gradually be reduced. */ /** How long the slip stream speed increase will gradually be reduced. */
float m_slipstream_fade_out_time; float m_slipstream_fade_out_time;
float m_camera_distance; /**< Distance of normal camera from kart.*/ /** Distance of normal camera from kart. */
float m_camera_forward_up_angle; /**< Up angle of the camera in relation to float m_camera_distance;
the pitch of the kart when driving
forwards. */ /** Up angle of the camera in relation to the pitch of the kart when
float m_camera_backward_up_angle; /**< Up angle of the camera in relation to * driving forwards. */
the pitch of the kart when driving float m_camera_forward_up_angle;
backwards. */
/** Up angle of the camera in relation to the pitch of the kart when
* driving backwards. */
float m_camera_backward_up_angle;
/** The following two vectors define at what ratio of the maximum speed what /** The following two vectors define at what ratio of the maximum speed what
* gear is selected. E.g. 0.25 means: if speed <=0.25*maxSpeed --> gear 1, * gear is selected. E.g. 0.25 means: if speed <=0.25*maxSpeed --> gear 1,
@ -337,12 +333,20 @@ public:
void checkAllSet (const std::string &filename); void checkAllSet (const std::string &filename);
float getStartupBoost () const; float getStartupBoost () const;
// ------------------------------------------------------------------------
/** Returns the (maximum) speed for a given turn radius.
* \param radius The radius for which the speed needs to be computed. */
float getSpeedForTurnRadius(float radius) const {
float angle = sin(m_wheel_base / radius);
return m_turn_angle_at_speed.getReverse(angle);
} // getSpeedForTurnRadius
// ------------------------------------------------------------------------
/** Returns the maximum steering angle (depending on speed). */ /** Returns the maximum steering angle (depending on speed). */
float getMaxSteerAngle (float speed) const; float getMaxSteerAngle(float speed) const {
return m_turn_angle_at_speed.get(speed);
/** Returns the (maximum) speed for a given turn radius. */ } // getMaxSteerAngle
float getSpeedForTurnRadius(float radius) const;
// ------------------------------------------------------------------------
/** Returns the material for the kart icons. */ /** Returns the material for the kart icons. */
Material* getIconMaterial () const {return m_icon_material; } Material* getIconMaterial () const {return m_icon_material; }
@ -360,7 +364,10 @@ public:
/** Returns the name of this kart. /** Returns the name of this kart.
\note Pass it through fridibi as needed, this is the LTR name \note Pass it through fridibi as needed, this is the LTR name
*/ */
const wchar_t* getName() const {return translations->w_gettext(m_name.c_str()); } const wchar_t* getName() const
{
return translations->w_gettext(m_name.c_str());
}
const std::string getNonTranslatedName() const {return m_name;} const std::string getNonTranslatedName() const {return m_name;}
@ -547,10 +554,16 @@ public:
/** Returns the increase of maximum speed while a rubber band is /** Returns the increase of maximum speed while a rubber band is
* pulling. */ * pulling. */
float getRubberBandSpeedIncrease() const {return m_rubber_band_speed_increase;} float getRubberBandSpeedIncrease() const
{
return m_rubber_band_speed_increase;
}
/** Return the fade out time once a rubber band is removed. */ /** Return the fade out time once a rubber band is removed. */
float getRubberBandFadeOutTime () const {return m_rubber_band_fade_out_time;} float getRubberBandFadeOutTime() const
{
return m_rubber_band_fade_out_time;
}
/** Returns duration of a plunger in your face. */ /** Returns duration of a plunger in your face. */
float getPlungerInFaceTime () const float getPlungerInFaceTime () const

View File

@ -0,0 +1,147 @@
//
// 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_INTERPOLATION_ARRAY_HPP
#define HEADER_INTERPOLATION_ARRAY_HPP
#include <assert.h>
#include <vector>
/** This class manages a set of (x_i,y_i) points, x_i must be sorted.
* Those values are then used to linearly interpolate the y value for a
* given x. If x is less than the minimum x_0, y_0 is returned, if x is
* more than the maximum x_n, y_n is returned.
*/
class InterpolationArray
{
private:
/** The sorted x values. */
std::vector<float> m_x;
/** The y values. */
std::vector<float> m_y;
/* Pre-computed (x[i+1]-x[i])/(y[i+1]/-y[i]) . */
std::vector<float> m_delta;
/** True if the Y values are decreasing. This flag is important when
* doing a reverse loopup (find X given Y). */
bool m_decreasing;
public:
InterpolationArray(bool decreasing) : m_decreasing(decreasing) {};
/** Adds the value pair x/y to the list of all points. It is tested
* that the x values are added in order.
* \param x, y The pair to add.
* \returns 0 If the x values are not sorted, 1 otherwise. */
int push_back(float x, float y)
{
if(m_x.size()>0 && x < m_x[m_x.size()-1])
return 0;
m_x.push_back(x);
m_y.push_back(y);
if(m_y.size()>1)
{
const unsigned int last=m_x.size()-1;
m_delta.push_back( (m_y[last]-m_y[last-1])
/(m_x[last]-m_x[last-1]) );
}
return 1;
} // push_back
// ------------------------------------------------------------------------
/** Returns the number of X/Y points. */
unsigned int size() const { return m_x.size(); }
// ------------------------------------------------------------------------
/** Returns the X value for a specified point. */
float getX(unsigned int i) const { return m_x[i]; }
// ------------------------------------------------------------------------
/** Returns the Y value for a specified point. */
float getY(unsigned int i) const { return m_y[i]; }
// ------------------------------------------------------------------------
/** Sets the Y value for a specified point. */
void setY(unsigned int i, float y)
{
m_y[i] = y;
if(i>0)
m_delta[i-1] = (m_y[i]-m_y[i-1])
/(m_x[i]-m_x[i-1]);
if(i<m_y.size()-1)
m_delta[i] = (m_y[i+1]-m_y[i])
/(m_x[i+1]-m_x[i]);
}
// ------------------------------------------------------------------------
/** Returns the interpolated Y value for a given x. */
float get(float x) const
{
if(m_x.size()==1 || x<m_x[0])
return m_y[0];
if(x>m_x[m_x.size()-1])
return m_y[m_y.size()-1];
// Now x must be between two points in m_x
// The array size in STK are pretty small (typically 3 or 4),
// so not worth the effort to do a binary search
for(unsigned int i=1; i<m_x.size(); i++)
{
if(x >m_x[i]) continue;
return m_y[i-1] + m_delta[i-1] * (x - m_x[i-1]);
}
assert(false); return 0; // keep compiler happy
} // get
// ------------------------------------------------------------------------
/** Returns the X value necessary for a specified Y value. If it's not
* possible to find a corresponding X (y is too small or too large),
* x_min or x_max is returned. */
float getReverse(float y) const
{
if(m_y.size()==1) return m_x[0];
if(m_decreasing)
{
if(y > m_y[0]) return m_x[0];
const unsigned int last = m_x.size();
for(unsigned int i=1; i<last; i++)
{
if(y < m_y[i]) continue;
return m_x[i-1] + (y-m_y[i-1])/ m_delta[i-1];
} // for i < last
return m_y[last-1];
}
else // increasing
{
if(y < m_y[0]) return m_x[0];
const unsigned int last = m_x.size();
for(unsigned int i=1; i<last; i++)
{
if(y > m_y[i]) continue;
return m_x[i-1] + (y-m_y[i-1]) / m_delta[i-1];
} // for i < last
return m_y[last-1];
} // increasing
} // getReverse
}; // InterpolationArray
#endif