From fbb9e5f8d23c05e004a4d401f416aafb0828933e Mon Sep 17 00:00:00 2001 From: hikerstk Date: Tue, 16 Oct 2012 05:51:46 +0000 Subject: [PATCH] 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 --- data/stk_config.xml | 11 +- sources.cmake | 27 ++--- src/ide/vc9/supertuxkart.vcproj | 4 + src/io/xml_node.cpp | 48 ++++++++ src/io/xml_node.hpp | 2 + src/karts/controller/ai_properties.cpp | 70 +----------- src/karts/controller/ai_properties.hpp | 18 +-- src/karts/kart_properties.cpp | 97 ++-------------- src/karts/kart_properties.hpp | 65 ++++++----- src/utils/interpolation_array.hpp | 147 +++++++++++++++++++++++++ 10 files changed, 284 insertions(+), 205 deletions(-) create mode 100644 src/utils/interpolation_array.hpp diff --git a/data/stk_config.xml b/data/stk_config.xml index 2c4b1fcab..2895b3d64 100644 --- a/data/stk_config.xml +++ b/data/stk_config.xml @@ -280,11 +280,11 @@ - - gear 1, - * 0.5 means: if speed <=0.5 *maxSpeed --> gear 2 */ + * gear is selected. E.g. 0.25 means: if speed <=0.25*maxSpeed --> gear 1, + * 0.5 means: if speed <=0.5 *maxSpeed --> gear 2 */ std::vector m_gear_switch_ratio; /** This vector contains the increase in max power (to simulate different * gears), e.g. 2.5 as first entry means: 2.5*maxPower in gear 1. See @@ -337,12 +333,20 @@ public: void checkAllSet (const std::string &filename); 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). */ - float getMaxSteerAngle (float speed) const; - - /** Returns the (maximum) speed for a given turn radius. */ - float getSpeedForTurnRadius(float radius) const; + float getMaxSteerAngle(float speed) const { + return m_turn_angle_at_speed.get(speed); + } // getMaxSteerAngle + // ------------------------------------------------------------------------ /** Returns the material for the kart icons. */ Material* getIconMaterial () const {return m_icon_material; } @@ -360,7 +364,10 @@ public: /** Returns the name of this kart. \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;} @@ -547,10 +554,16 @@ public: /** Returns the increase of maximum speed while a rubber band is * 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. */ - 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. */ float getPlungerInFaceTime () const diff --git a/src/utils/interpolation_array.hpp b/src/utils/interpolation_array.hpp new file mode 100644 index 000000000..4675591cd --- /dev/null +++ b/src/utils/interpolation_array.hpp @@ -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 +#include + +/** 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 m_x; + + /** The y values. */ + std::vector m_y; + + /* Pre-computed (x[i+1]-x[i])/(y[i+1]/-y[i]) . */ + std::vector 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(im_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; im_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 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