From 6e5086f9b8c729d16f6498958d0d85a34d9b0e7f Mon Sep 17 00:00:00 2001 From: hikerstk Date: Thu, 4 Aug 2011 23:33:41 +0000 Subject: [PATCH] More refactoring: duplicated code handling track sectors and distance along track is now moved into a separate class TrackSector and used in linear_world and rubber ball. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@9422 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- CMakeLists.txt | 2 + src/Makefile.am | 2 + src/ide/vc9/supertuxkart.vcproj | 8 +++ src/items/rubber_ball.cpp | 21 +++--- src/items/rubber_ball.hpp | 3 +- src/modes/linear_world.cpp | 120 +++++--------------------------- src/modes/linear_world.hpp | 65 +++++++++++------ src/tracks/quad_graph.cpp | 9 +-- src/tracks/track_sector.cpp | 91 ++++++++++++++++++++++++ src/tracks/track_sector.hpp | 75 ++++++++++++++++++++ 10 files changed, 259 insertions(+), 137 deletions(-) create mode 100644 src/tracks/track_sector.cpp create mode 100644 src/tracks/track_sector.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 24dbd3be2..1d22d16c8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -566,6 +566,8 @@ add_executable(supertuxkart src/tracks/track_object.hpp src/tracks/track_object_manager.cpp src/tracks/track_object_manager.hpp + src/tracks/track_sector.cpp + src/tracks/track_sector.hpp src/tutorial/tutorial.cpp src/tutorial/tutorial_data.cpp src/tutorial/tutorial_data.hpp diff --git a/src/Makefile.am b/src/Makefile.am index 6ebbb79a2..c761570b3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -434,6 +434,8 @@ supertuxkart_SOURCES = \ tracks/track_object.hpp \ tracks/track_object_manager.cpp \ tracks/track_object_manager.hpp \ + tracks/track_sector.cpp \ + tracks/track_sector.hpp \ tutorial/tutorial.cpp \ tutorial/tutorial.hpp \ tutorial/tutorial_data.cpp \ diff --git a/src/ide/vc9/supertuxkart.vcproj b/src/ide/vc9/supertuxkart.vcproj index 126c64e0e..967e41342 100644 --- a/src/ide/vc9/supertuxkart.vcproj +++ b/src/ide/vc9/supertuxkart.vcproj @@ -874,6 +874,10 @@ RelativePath="..\..\tracks\track_object_manager.cpp" > + + + + getKartLength() + m_extend.getZ()*0.5f+5.0f; @@ -62,13 +63,15 @@ RubberBall::RubberBall(Kart *kart) : Flyable(kart, PowerupManager::POWERUP_RUBBE // Get 4 points for the interpolation int pred = QuadGraph::get()->getNode(m_current_graph_node) - .getPredecessor(); + .getPredecessor(); m_aiming_points[0] = QuadGraph::get()->getQuadOfNode(pred).getCenter(); m_aiming_points[1] = QuadGraph::get()->getQuadOfNode(m_current_graph_node) - .getCenter(); - m_aiming_points[2] = QuadGraph::get()->getQuadOfNode(m_aimed_graph_node).getCenter(); + .getCenter(); + m_aiming_points[2] = QuadGraph::get()->getQuadOfNode(m_aimed_graph_node) + .getCenter(); int succ_succ = getSuccessorToHitTarget(m_aimed_graph_node); - m_aiming_points[3] = QuadGraph::get()->getQuadOfNode(succ_succ).getCenter(); + m_aiming_points[3] = QuadGraph::get()->getQuadOfNode(succ_succ) + .getCenter(); m_t = 0; m_t_increase = 1.0f/(m_aiming_points[2]-m_aiming_points[1]).length(); @@ -172,16 +175,18 @@ void RubberBall::update(float dt) int indx = getSuccessorToHitTarget(m_current_graph_node); // Determine new distance along track + TrackSector::update(next_xyz); + Vec3 ball_distance_vec; QuadGraph::get()->findRoadSector(next_xyz, &m_current_graph_node); if(m_current_graph_node == QuadGraph::UNKNOWN_SECTOR) { m_current_graph_node = QuadGraph::get()->findOutOfRoadSector(next_xyz, - QuadGraph::UNKNOWN_SECTOR ); + QuadGraph::UNKNOWN_SECTOR ); } QuadGraph::get()->spatialToTrack(&ball_distance_vec, getXYZ(), - m_current_graph_node); + m_current_graph_node); // Detect wrap around, i.e. crossing the start line float old_distance = m_distance_along_track; diff --git a/src/items/rubber_ball.hpp b/src/items/rubber_ball.hpp index 73c39280a..1023c1996 100644 --- a/src/items/rubber_ball.hpp +++ b/src/items/rubber_ball.hpp @@ -21,6 +21,7 @@ #define HEADER_RUBBER_BALL_HPP #include "items/flyable.hpp" +#include "tracks/track_sector.hpp" class Kart; class QuadGraph; @@ -28,7 +29,7 @@ class QuadGraph; /** * \ingroup items */ -class RubberBall: public Flyable +class RubberBall: public Flyable, public TrackSector { private: /** A class variable to store the default interval size. */ diff --git a/src/modes/linear_world.cpp b/src/modes/linear_world.cpp index e6d18ca30..c7062ef5f 100644 --- a/src/modes/linear_world.cpp +++ b/src/modes/linear_world.cpp @@ -25,6 +25,7 @@ #include "audio/sfx_manager.hpp" #include "network/network_manager.hpp" #include "race/history.hpp" +#include "tracks/track_sector.hpp" #include "tracks/track.hpp" #include "utils/constants.hpp" #include "utils/string_utils.hpp" @@ -61,31 +62,7 @@ void LinearWorld::init() for(unsigned int n=0; nfindRoadSector(m_karts[n]->getXYZ(), - &info.m_track_sector); - - //If m_track_sector == UNKNOWN_SECTOR, then the kart is not on top of - //the road, so we have to use another function to find the sector. - info.m_on_road = info.m_track_sector != QuadGraph::UNKNOWN_SECTOR; - if (!info.m_on_road) - { - info.m_track_sector = - QuadGraph::get()->findOutOfRoadSector(m_karts[n]->getXYZ(), - QuadGraph::UNKNOWN_SECTOR ); - } - - QuadGraph::get()->spatialToTrack(&info.m_curr_track_coords, - m_karts[n]->getXYZ(), - info.m_track_sector ); - - info.m_race_lap = -1; - info.m_lap_start_time = 0; - info.m_time_at_last_lap = 99999.9f; - info.m_estimated_finish = -1.0f; - + info.getSector()->update(m_karts[n]->getXYZ()); m_kart_info.push_back(info); } // next kart @@ -114,29 +91,8 @@ void LinearWorld::restartRace() const unsigned int kart_amount = m_karts.size(); for(unsigned int i=0; ifindRoadSector(m_karts[i]->getXYZ(), - &info.m_track_sector); - - //If m_track_sector == UNKNOWN_SECTOR, then the kart is not on top of - //the road, so we have to use another function to find the sector. - info.m_on_road = info.m_track_sector != QuadGraph::UNKNOWN_SECTOR; - if (!info.m_on_road) - { - info.m_track_sector = - QuadGraph::get()->findOutOfRoadSector(m_karts[i]->getXYZ(), - QuadGraph::UNKNOWN_SECTOR); - } - - QuadGraph::get()->spatialToTrack(&info.m_curr_track_coords, - m_karts[i]->getXYZ(), - info.m_track_sector ); - info.m_race_lap = -1; - info.m_lap_start_time = -0; - info.m_time_at_last_lap = 99999.9f; + m_kart_info[i].reset(); + m_kart_info[i].getSector()->update(m_karts[i]->getXYZ()); } // next kart // First all kart infos must be updated before the kart position can be @@ -193,30 +149,7 @@ void LinearWorld::update(float dt) // Nothing to do for karts that are currently being rescued or eliminated if(kart->playingEmergencyAnimation()) continue; - // ---------- deal with sector data --------- - - // update sector variables - int prev_sector = kart_info.m_track_sector; - QuadGraph::get()->findRoadSector(kart->getXYZ(), - &kart_info.m_track_sector); - - kart_info.m_on_road = kart_info.m_track_sector != QuadGraph::UNKNOWN_SECTOR; - if(kart_info.m_on_road) - { - kart_info.m_last_valid_sector = kart_info.m_track_sector; - } - else - { - // Kart off road. Find the closest sector instead. - kart_info.m_track_sector = - QuadGraph::get()->findOutOfRoadSector(kart->getXYZ(), prev_sector ); - } - - // Update track coords (=progression) - QuadGraph::get()->spatialToTrack(&kart_info.m_curr_track_coords, - kart->getXYZ(), - kart_info.m_track_sector ); - + kart_info.getSector()->update(kart->getXYZ()); } // for n // Update all positions. This must be done after _all_ karts have @@ -390,7 +323,7 @@ void LinearWorld::newLap(unsigned int kart_index) //----------------------------------------------------------------------------- int LinearWorld::getSectorForKart(const int kart_id) const { - return m_kart_info[kart_id].m_track_sector; + return m_kart_info[kart_id].getSector()->getCurrentGraphNode(); } // getSectorForKart //----------------------------------------------------------------------------- @@ -400,7 +333,7 @@ int LinearWorld::getSectorForKart(const int kart_id) const */ float LinearWorld::getDistanceDownTrackForKart(const int kart_id) const { - return m_kart_info[kart_id].m_curr_track_coords.getZ(); + return m_kart_info[kart_id].getSector()->getDistanceFromStart(); } // getDistanceDownTrackForKart //----------------------------------------------------------------------------- @@ -410,7 +343,7 @@ float LinearWorld::getDistanceDownTrackForKart(const int kart_id) const */ float LinearWorld::getDistanceToCenterForKart(const int kart_id) const { - return m_kart_info[kart_id].m_curr_track_coords.getX(); + return m_kart_info[kart_id].getSector()->getDistanceToCenter(); } // getDistanceToCenterForKart //----------------------------------------------------------------------------- @@ -566,31 +499,13 @@ void LinearWorld::moveKartAfterRescue(Kart* kart) { KartInfo& info = m_kart_info[kart->getWorldKartId()]; - // If the kart is off road, rescue it to the last valid track position - // instead of the current one (since the sector might be determined by - // being closest to it, which allows shortcuts like drive towards another - // part of the lap, press rescue, and be rescued to this other part of - // the track (example: math class, drive towards the left after start, - // when hitting the books, press rescue --> you are rescued to the - // end of the track). - if(!info.m_on_road) - { - info.m_track_sector = info.m_last_valid_sector; - } - - // Using the predecessor has the additional afvantage (besides punishing - // the player a bit more) that it makes it less likely to fall in a - // rescue loop since the kart moves back on each attempt. - info.m_track_sector = QuadGraph::get()->getNode(info.m_track_sector) - .getPredecessor(); - info.m_last_valid_sector= QuadGraph::get()->getNode(info.m_track_sector) - .getPredecessor(); - - kart->setXYZ( QuadGraph::get()->getQuadOfNode(info.m_track_sector) - .getCenter()); + info.getSector()->rescue(); + int sector = info.getSector()->getCurrentGraphNode(); + kart->setXYZ( QuadGraph::get() + ->getQuadOfNode(sector).getCenter()); btQuaternion heading(btVector3(0.0f, 1.0f, 0.0f), - m_track->getAngle(info.m_track_sector) ); + m_track->getAngle(sector) ); kart->setRotation(heading); // A certain epsilon is added here to the Z coordinate, in case @@ -602,7 +517,7 @@ void LinearWorld::moveKartAfterRescue(Kart* kart) btTransform pos; pos.setOrigin(kart->getXYZ()+btVector3(0, kart->getKartHeight() + epsilon, 0)); pos.setRotation(btQuaternion(btVector3(0.0f, 1.0f, 0.0f), - m_track->getAngle(info.m_track_sector))); + m_track->getAngle(sector))); kart->getBody()->setCenterOfMassTransform(pos); @@ -815,19 +730,20 @@ void LinearWorld::updateRacePosition() void LinearWorld::checkForWrongDirection(unsigned int i) { if(!m_karts[i]->getController()->isPlayerController()) return; - if(!m_kart_info[i].m_on_road || + if(!m_kart_info[i].getSector()->isOnRoad()|| m_karts[i]->playingEmergencyAnimation()) return; const Kart *kart=m_karts[i]; // If the kart can go in more than one directions from the current track // don't do any reverse message handling, since it is likely that there // will be one direction in which it isn't going backwards anyway. - if(QuadGraph::get()->getNumberOfSuccessors(m_kart_info[i].m_track_sector)>1) + int sector = m_kart_info[i].getSector()->getCurrentGraphNode(); + if(QuadGraph::get()->getNumberOfSuccessors(sector)>1) return; // check if the player is going in the wrong direction float angle_diff = kart->getHeading() - - m_track->getAngle(m_kart_info[i].m_track_sector); + m_track->getAngle(sector); if(angle_diff > M_PI) angle_diff -= 2*M_PI; else if (angle_diff < -M_PI) angle_diff += 2*M_PI; // Display a warning message if the kart is going back way (unless diff --git a/src/modes/linear_world.hpp b/src/modes/linear_world.hpp index 0b92dbb93..bf314ed2e 100644 --- a/src/modes/linear_world.hpp +++ b/src/modes/linear_world.hpp @@ -21,6 +21,7 @@ #include #include "modes/world_with_rank.hpp" +#include "tracks/track_sector.hpp" #include "utils/aligned_array.hpp" class SFXBase; @@ -33,6 +34,7 @@ class SFXBase; */ class LinearWorld : public WorldWithRank { +private: /** Sfx for the final lap. */ SFXBase *m_last_lap_sfx; @@ -41,27 +43,48 @@ class LinearWorld : public WorldWithRank bool m_last_lap_sfx_playing; -private: + // ------------------------------------------------------------------------ /** Some additional info that needs to be kept for each kart * in this kind of race. */ - struct KartInfo + class KartInfo { - int m_race_lap; /**isOnRoad(); } }; // LinearWorld #endif diff --git a/src/tracks/quad_graph.cpp b/src/tracks/quad_graph.cpp index a03b60e00..f2a977b74 100644 --- a/src/tracks/quad_graph.cpp +++ b/src/tracks/quad_graph.cpp @@ -516,12 +516,9 @@ void QuadGraph::spatialToTrack(Vec3 *dst, const Vec3& xyz, //----------------------------------------------------------------------------- /** findRoadSector returns in which sector on the road the position - * xyz is. If xyz is not on top of the road, it returns - * UNKNOWN_SECTOR. + * xyz is. If xyz is not on top of the road, it sets UNKNOWN_SECTOR as sector. * - * The 'sector' could be defined as the number of the closest track - * segment to XYZ. - * \param XYZ Position for which the segment should be determined. + * \param xyz Position for which the segment should be determined. * \param sector Contains the previous sector (as a shortcut, since usually * the sector is the same as the last one), and on return the result * \param all_sectors If this is not NULL, it is a list of all sectors to @@ -565,7 +562,7 @@ void QuadGraph::findRoadSector(const Vec3& xyz, int *sector, indx = indx<(int)m_all_nodes.size()-1 ? indx +1 : 0; const Quad &q = getQuadOfNode(indx); float dist = xyz.getY() - q.getMinHeight(); - // While negative distances are unlikely, we allow some small netative + // While negative distances are unlikely, we allow some small negative // numbers in case that the kart is partly in the track. if(q.pointInQuad(xyz) && dist < min_dist && dist>-1.0f) { diff --git a/src/tracks/track_sector.cpp b/src/tracks/track_sector.cpp new file mode 100644 index 000000000..29665c732 --- /dev/null +++ b/src/tracks/track_sector.cpp @@ -0,0 +1,91 @@ +// $Id$ +// +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2011 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 "tracks/track_sector.hpp" +#include "tracks/quad_graph.hpp" + + +// ---------------------------------------------------------------------------- +/** Initialises the object, and sets the current graph node to be undefined. + */ +TrackSector::TrackSector() +{ + reset(); +} // TrackSector + +// ---------------------------------------------------------------------------- +void TrackSector::reset() +{ + m_current_graph_node = QuadGraph::UNKNOWN_SECTOR; + m_last_valid_graph_node = QuadGraph::UNKNOWN_SECTOR; + m_on_road = false; +} // reset + +// ---------------------------------------------------------------------------- +/** Updates the current graph node index, and the track coordinates for + * the specified point. + * \param xyz The new coordinates to search the graph node for. + */ +void TrackSector::update(const Vec3 &xyz) +{ + int prev_sector = m_current_graph_node; + + QuadGraph::get()->findRoadSector(xyz, &m_current_graph_node); + m_on_road = m_current_graph_node != QuadGraph::UNKNOWN_SECTOR; + + // If m_track_sector == UNKNOWN_SECTOR, then the kart is not on top of + // the road, so we have to use search for the closest graph node. + if(m_current_graph_node == QuadGraph::UNKNOWN_SECTOR) + { + m_current_graph_node = + QuadGraph::get()->findOutOfRoadSector(xyz, + prev_sector); + } + else + m_last_valid_graph_node = m_current_graph_node; + + // Now determine the 'track' coords, i.e. ow far from the start of the + // track, and how far to the left or right of the center driveline. + QuadGraph::get()->spatialToTrack(&m_current_track_coords, xyz, + m_current_graph_node); +} // update + +// ---------------------------------------------------------------------------- +void TrackSector::rescue() +{ + // If the kart is off road, rescue it to the last valid track position + // instead of the current one (since the sector might be determined by + // being closest to it, which allows shortcuts like drive towards another + // part of the lap, press rescue, and be rescued to this other part of + // the track (example: math class, drive towards the left after start, + // when hitting the books, press rescue --> you are rescued to the + // end of the track). + if(!isOnRoad()) + { + m_current_graph_node = m_last_valid_graph_node; + } + + // Using the predecessor has the additional advantage (besides punishing + // the player a bit more) that it makes it less likely to fall in a + // rescue loop since the kart moves back on each attempt. + m_current_graph_node = QuadGraph::get()->getNode(m_current_graph_node) + .getPredecessor(); + m_last_valid_graph_node = QuadGraph::get()->getNode(m_current_graph_node) + .getPredecessor(); +} // rescue \ No newline at end of file diff --git a/src/tracks/track_sector.hpp b/src/tracks/track_sector.hpp new file mode 100644 index 000000000..0d0f62a74 --- /dev/null +++ b/src/tracks/track_sector.hpp @@ -0,0 +1,75 @@ +// $Id$ +// +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2011 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_TRACK_SECTOR_HPP +#define HEADER_TRACK_SECTOR_HPP + +#include "utils/vec3.hpp" + +/** This object keeps track of which sector an object is on. A sector is + * actually just the graph node (it's called sector to better distinguish + * the graph node from say xml node and scene node). + * An object that has a track sector can determine how far away it is from + * the start line, how far away it is from the center driveline. If the + * object is not actually on part of the quad graph, it will determine the + * closest sector it is to, and set a flag (!isOnRoad). + * This object will also keep track on the last valid sector an object was + * on, which is used to reset a kart in case of a rescue. + + */ +class TrackSector +{ +private: + /** The graph node the object is on. */ + int m_current_graph_node; + + /** The index of the last valid graph node. */ + int m_last_valid_graph_node; + + /** The coordinates of this object on the track, i.e. how far from + * the start of the track, and how far to the left or right + * of the center driveline. */ + Vec3 m_current_track_coords; + + /** True if the object is on the road (driveline), or not. */ + bool m_on_road; + + +public: + TrackSector(); + void reset(); + void rescue(); + void update(const Vec3 &xyz); + // ------------------------------------------------------------------------ + /** Returns how far the the object is from the start line. */ + float getDistanceFromStart() const { return m_current_track_coords.getZ();} + // ------------------------------------------------------------------------ + /** Returns the distance to the centre driveline. */ + float getDistanceToCenter() const { return m_current_track_coords.getX(); } + // ------------------------------------------------------------------------ + /** Returns the current graph node. */ + int getCurrentGraphNode() const {return m_current_graph_node;} + // ------------------------------------------------------------------------ + /** Returns if this object is on the road (driveline). */ + bool isOnRoad() const { return m_on_road; } + +}; // TrackSector + +#endif +