diff --git a/src/modes/cutscene_world.cpp b/src/modes/cutscene_world.cpp index 0abc4b577..ab56220d9 100644 --- a/src/modes/cutscene_world.cpp +++ b/src/modes/cutscene_world.cpp @@ -416,37 +416,11 @@ bool CutsceneWorld::isRaceOver() return m_time > m_duration; } // isRaceOver -//----------------------------------------------------------------------------- -/** Called when the race finishes, i.e. after playing (if necessary) an - * end of race animation. It updates the time for all karts still racing, - * and then updates the ranks. - */ -void CutsceneWorld::terminateRace() -{ - World::terminateRace(); -} // terminateRace - -//----------------------------------------------------------------------------- -/** Returns the data to display in the race gui. - */ -void CutsceneWorld::getKartsDisplayInfo( - std::vector *info) -{ -} // getKartDisplayInfo - -//----------------------------------------------------------------------------- -/** Moves a kart to its rescue position. - * \param kart The kart that was rescued. - */ -void CutsceneWorld::moveKartAfterRescue(AbstractKart* kart) -{ -} // moveKartAfterRescue - //----------------------------------------------------------------------------- void CutsceneWorld::createRaceGUI() { m_race_gui = new CutsceneGUI(); -} +} // createRaceGUI diff --git a/src/modes/cutscene_world.hpp b/src/modes/cutscene_world.hpp index 022aa017b..a1b5025ef 100644 --- a/src/modes/cutscene_world.hpp +++ b/src/modes/cutscene_world.hpp @@ -68,17 +68,6 @@ public: // clock events virtual bool isRaceOver() OVERRIDE; - virtual void terminateRace() OVERRIDE; - - void setParts(std::vector parts) - { - m_parts = parts; - } - - virtual void getKartsDisplayInfo( - std::vector *info) OVERRIDE; - virtual bool raceHasLaps() OVERRIDE { return false; } - virtual void moveKartAfterRescue(AbstractKart* kart) OVERRIDE; virtual const std::string& getIdent() const OVERRIDE; @@ -88,8 +77,35 @@ public: virtual void enterRaceOverState() OVERRIDE; + // ------------------------------------------------------------------------ + virtual bool raceHasLaps() OVERRIDE { return false; } + // ------------------------------------------------------------------------ + virtual unsigned int getNumberOfRescuePositions() const OVERRIDE + { + return 0; + } // getNumberOfRescuePositions + // ------------------------------------------------------------------------ + virtual unsigned int getRescuePositionIndex(AbstractKart *kart) OVERRIDE + { + return 0; + } // getRescuePositionIndex + // ------------------------------------------------------------------------ + virtual btTransform getRescueTransform(unsigned int index) const OVERRIDE + { + return btTransform(); + } // getRescueTransform + // ------------------------------------------------------------------------ virtual void onFirePressed(Controller* who) OVERRIDE { abortCutscene(); } - + // ------------------------------------------------------------------------ + void setParts(std::vector parts) { m_parts = parts; } + // ------------------------------------------------------------------------ + /** Returns the data to display in the race gui. + */ + virtual void getKartsDisplayInfo( + std::vector *info) OVERRIDE + { + }; + // ------------------------------------------------------------------------ virtual void escapePressed() OVERRIDE { abortCutscene(); } }; // CutsceneWorld diff --git a/src/modes/easter_egg_hunt.cpp b/src/modes/easter_egg_hunt.cpp index f50e81b00..107df704d 100644 --- a/src/modes/easter_egg_hunt.cpp +++ b/src/modes/easter_egg_hunt.cpp @@ -206,15 +206,3 @@ void EasterEggHunt::getKartsDisplayInfo( } } // getKartDisplayInfo -//----------------------------------------------------------------------------- -/** Moves a kart to its rescue position. - * \param kart The kart that was rescued. - */ -void EasterEggHunt::moveKartAfterRescue(AbstractKart* kart) -{ - int start_position = kart->getInitialPosition(); - btTransform start_pos = getTrack()->getStartTransform(start_position-1); - - kart->getBody()->setCenterOfMassTransform(start_pos); - -} // moveKartAfterRescue diff --git a/src/modes/easter_egg_hunt.hpp b/src/modes/easter_egg_hunt.hpp index 11db3cef6..31ba96fb4 100755 --- a/src/modes/easter_egg_hunt.hpp +++ b/src/modes/easter_egg_hunt.hpp @@ -54,7 +54,6 @@ public: virtual void reset(); virtual bool raceHasLaps(){ return false; } - virtual void moveKartAfterRescue(AbstractKart* kart); virtual const std::string& getIdent() const; diff --git a/src/modes/linear_world.cpp b/src/modes/linear_world.cpp index d7aa84f17..c519703c1 100644 --- a/src/modes/linear_world.cpp +++ b/src/modes/linear_world.cpp @@ -89,7 +89,7 @@ void LinearWorld::reset() for(unsigned int i=0; iupdate(m_karts[i]->getXYZ()); + m_kart_info[i].getTrackSector()->update(m_karts[i]->getXYZ()); } // next kart // At the moment the last kart would be the one that is furthest away @@ -172,7 +172,7 @@ void LinearWorld::update(float dt) // rescued or eliminated if(kart->getKartAnimation()) continue; - kart_info.getSector()->update(kart->getXYZ()); + kart_info.getTrackSector()->update(kart->getXYZ()); kart_info.m_overall_distance = kart_info.m_race_lap * m_track->getTrackLength() + getDistanceDownTrackForKart(kart->getWorldKartId()); @@ -376,7 +376,7 @@ int LinearWorld::getSectorForKart(const AbstractKart *kart) const { if(kart->getWorldKartId()>=m_kart_info.size()) return QuadGraph::UNKNOWN_SECTOR; - return m_kart_info[kart->getWorldKartId()].getSector() + return m_kart_info[kart->getWorldKartId()].getTrackSector() ->getCurrentGraphNode(); } // getSectorForKart @@ -388,7 +388,7 @@ int LinearWorld::getSectorForKart(const AbstractKart *kart) const float LinearWorld::getDistanceDownTrackForKart(const int kart_id) const { assert(kart_id < (int)m_kart_info.size()); - return m_kart_info[kart_id].getSector()->getDistanceFromStart(); + return m_kart_info[kart_id].getTrackSector()->getDistanceFromStart(); } // getDistanceDownTrackForKart //----------------------------------------------------------------------------- @@ -399,7 +399,7 @@ float LinearWorld::getDistanceDownTrackForKart(const int kart_id) const float LinearWorld::getDistanceToCenterForKart(const int kart_id) const { assert(kart_id < (int)m_kart_info.size()); - return m_kart_info[kart_id].getSector()->getDistanceToCenter(); + return m_kart_info[kart_id].getTrackSector()->getDistanceToCenter(); } // getDistanceToCenterForKart //----------------------------------------------------------------------------- @@ -605,58 +605,37 @@ float LinearWorld::estimateFinishTimeForKart(AbstractKart* kart) return est_time; } // estimateFinishTimeForKart -//----------------------------------------------------------------------------- -/** Decide where to drop a rescued kart +// ------------------------------------------------------------------------ +/** Returns the number of rescue positions on a given track, which in + * linear races is just the number of driveline quads. */ -void LinearWorld::moveKartAfterRescue(AbstractKart* kart) +unsigned int LinearWorld::getNumberOfRescuePositions() const +{ + return QuadGraph::get()->getNumNodes(); +} // getNumberOfRescuePositions + +// ------------------------------------------------------------------------ +unsigned int LinearWorld::getRescuePositionIndex(AbstractKart *kart) { KartInfo& info = m_kart_info[kart->getWorldKartId()]; - info.getSector()->rescue(); + info.getTrackSector()->rescue(); // Setting XYZ for the kart is important since otherwise the kart // will not detect the right material again when doing the next // raycast to detect where it is driving on (--> potential rescue loop) - int sector = info.getSector()->getCurrentGraphNode(); - kart->setXYZ( QuadGraph::get()->getQuadOfNode(sector).getCenter()); + return info.getTrackSector()->getCurrentGraphNode(); +} // getRescuePositionIndex - btQuaternion heading(btVector3(0.0f, 1.0f, 0.0f), - m_track->getAngle(sector) ); - kart->setRotation(heading); - // A certain epsilon is added here to the Z coordinate, in case - // that the drivelines are somewhat under the track. Otherwise, the - // kart might be placed a little bit under the track, triggering - // a rescue, ... (experimentally found value) - float epsilon = 0.5f * kart->getKartHeight(); - const Vec3 &xyz = QuadGraph::get()->getQuadOfNode(sector).getCenter(); +// ------------------------------------------------------------------------ +btTransform LinearWorld::getRescueTransform(unsigned int index) const +{ + const Vec3 &xyz = QuadGraph::get()->getQuadOfNode(index).getCenter(); btTransform pos; - pos.setOrigin(xyz+btVector3(0, kart->getKartHeight() + epsilon,0)); + pos.setOrigin(xyz); pos.setRotation(btQuaternion(btVector3(0.0f, 1.0f, 0.0f), - m_track->getAngle(sector))); - - kart->getBody()->setCenterOfMassTransform(pos); - kart->setXYZ(pos.getOrigin()); - //project kart to surface of track - bool kart_over_ground = m_track->findGround(kart); - - if (kart_over_ground) - { - //add vertical offset so that the kart starts off above the track - float vertical_offset = - kart->getKartProperties()->getVertRescueOffset() - * kart->getKartHeight(); - kart->getBody()->translate(btVector3(0, vertical_offset, 0)); - // Also correctly set the graphics, otherwise the kart will - // be displayed for one frame at the incorrect position. - kart->updateGraphics(0, Vec3(0,0,0), btQuaternion(0, 0, 0, 1)); - } - else - { - fprintf(stderr, "WARNING: invalid position after rescue for kart %s " - "on track %s.\n", - (kart->getIdent().c_str()), m_track->getIdent().c_str()); - } - -} // moveKartAfterRescue + m_track->getAngle(index))); + return pos; +} // getRescueTransform //----------------------------------------------------------------------------- /** Find the position (rank) of every kart. ATM it uses a stable O(n^2) @@ -849,14 +828,14 @@ void LinearWorld::updateRacePosition() void LinearWorld::checkForWrongDirection(unsigned int i) { if(!m_karts[i]->getController()->isPlayerController()) return; - if(!m_kart_info[i].getSector()->isOnRoad()|| + if(!m_kart_info[i].getTrackSector()->isOnRoad()|| m_karts[i]->getKartAnimation()) return; const AbstractKart *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. - int sector = m_kart_info[i].getSector()->getCurrentGraphNode(); + int sector = m_kart_info[i].getTrackSector()->getCurrentGraphNode(); if(QuadGraph::get()->getNumberOfSuccessors(sector)>1) return; diff --git a/src/modes/linear_world.hpp b/src/modes/linear_world.hpp index ececb9e1d..15ed57ed7 100644 --- a/src/modes/linear_world.hpp +++ b/src/modes/linear_world.hpp @@ -79,7 +79,7 @@ private: float m_overall_distance; /** Stores the current graph node and track coordinates etc. */ - TrackSector m_current_sector; + TrackSector m_track_sector; /** Initialises all fields. */ KartInfo() { reset(); } @@ -92,14 +92,14 @@ private: m_time_at_last_lap = 99999.9f; m_estimated_finish = -1.0f; m_overall_distance = 0.0f; - m_current_sector.reset(); + m_track_sector.reset(); } // reset // -------------------------------------------------------------------- /** Returns a pointer to the current node object. */ - TrackSector *getSector() {return &m_current_sector; } + TrackSector *getTrackSector() {return &m_track_sector; } // -------------------------------------------------------------------- /** Returns a pointer to the current node object. */ - const TrackSector *getSector() const {return &m_current_sector; } + const TrackSector *getTrackSector() const {return &m_track_sector; } }; // ------------------------------------------------------------------------ @@ -133,7 +133,10 @@ public: virtual void getKartsDisplayInfo( std::vector *info) OVERRIDE; - virtual void moveKartAfterRescue(AbstractKart* kart) OVERRIDE; + + virtual unsigned int getNumberOfRescuePositions() const OVERRIDE; + virtual unsigned int getRescuePositionIndex(AbstractKart *kart) OVERRIDE; + virtual btTransform getRescueTransform(unsigned int index) const OVERRIDE; virtual void reset() OVERRIDE; virtual void newLap(unsigned int kart_index) OVERRIDE; @@ -151,7 +154,7 @@ public: * \param kart_index Index of the kart. */ bool isOnRoad(unsigned int kart_index) const { - return m_kart_info[kart_index].getSector()->isOnRoad(); + return m_kart_info[kart_index].getTrackSector()->isOnRoad(); } // isOnRoad // ------------------------------------------------------------------------ @@ -168,7 +171,7 @@ public: * \param kart_index World index of the kart. */ TrackSector& getTrackSector(unsigned int kart_index) { - return m_kart_info[kart_index].m_current_sector; + return m_kart_info[kart_index].m_track_sector; } // getTrackSector // ------------------------------------------------------------------------ diff --git a/src/modes/overworld.cpp b/src/modes/overworld.cpp index 35c395d59..65cdf8f10 100644 --- a/src/modes/overworld.cpp +++ b/src/modes/overworld.cpp @@ -34,9 +34,9 @@ #include "tracks/track.hpp" //----------------------------------------------------------------------------- -OverWorld::OverWorld() : LinearWorld() +OverWorld::OverWorld() : WorldWithRank() { - m_return_to_garage = false; + m_return_to_garage = false; m_stop_music_when_dialog_open = false; } // Overworld @@ -115,7 +115,7 @@ void OverWorld::update(float dt) music_manager->getCurrentMusic()->startMusic(); m_karts[0]->startEngineSFX(); } - LinearWorld::update(dt); + WorldWithRank::update(dt); const unsigned int kart_amount = m_karts.size(); // isn't it cool, on the overworld nitro is free! @@ -136,6 +136,15 @@ void OverWorld::update(float dt) } } // update +//----------------------------------------------------------------------------- +/** This function is not used in the overworld race gui. + */ +void OverWorld::getKartsDisplayInfo( + std::vector *info) +{ + assert(false); +} // getKartsDisplayInfo + //----------------------------------------------------------------------------- /** Override the base class method to change behavior. We don't want wrong * direction messages in the overworld since there is no direction there. @@ -191,96 +200,6 @@ void OverWorld::onFirePressed(Controller* who) } // end for } // onFirePressed -//----------------------------------------------------------------------------- - -btTransform OverWorld::getClosestStartPoint(float currentKart_x, - float currentKart_z) -{ - // find closest point to drop kart on - World *world = World::getWorld(); - const int start_spots_amount = - world->getTrack()->getNumberOfStartPositions(); - assert(start_spots_amount > 0); - - - int closest_id = -1; - float closest_distance = 999999999.0f; - - for (int n=0; ngetTrack()->getStartTransform(n); - const Vec3 &v = s.getOrigin(); - - float absDistance = fabs(currentKart_x - v.getX()) + - fabs(currentKart_z - v.getZ()); - - if (absDistance < closest_distance) - { - closest_distance = absDistance; - closest_id = n; - } - } - - assert(closest_id != -1); - return world->getTrack()->getStartTransform(closest_id); -} // getClosestStartPoint - -//----------------------------------------------------------------------------- -/** Moves a kart to its rescue position. - * \param kart The kart that was rescued. - */ -void OverWorld::moveKartAfterRescue(AbstractKart* kart) -{ - moveKartAfterRescue(kart, 0); -} // moveKartAfterRescue(AbstractKart*) - -//----------------------------------------------------------------------------- - -void OverWorld::moveKartAfterRescue(AbstractKart* kart, float angle) -{ - // find closest point to drop kart on - World *world = World::getWorld(); - const int start_spots_amount = - world->getTrack()->getNumberOfStartPositions(); - assert(start_spots_amount > 0); - - const float currentKart_x = kart->getXYZ().getX(); - const float currentKart_z = kart->getXYZ().getZ(); - - const btTransform& s = getClosestStartPoint(currentKart_x, currentKart_z); - const Vec3 &xyz = s.getOrigin(); - kart->setXYZ(xyz); - kart->setRotation(s.getRotation()); - - //position kart from same height as in World::resetAllKarts - btTransform pos; - pos.setOrigin( kart->getXYZ() - +btVector3(0, 0.5f*kart->getKartHeight(), 0.0f) ); - pos.setRotation( btQuaternion(btVector3(0.0f, 1.0f, 0.0f), angle) ); - - kart->getBody()->setCenterOfMassTransform(pos); - - //project kart to surface of track - bool kart_over_ground = m_track->findGround(kart); - - if (kart_over_ground) - { - //add vertical offset so that the kart starts off above the track - float vertical_offset = - kart->getKartProperties()->getVertRescueOffset() - * kart->getKartHeight(); - kart->getBody()->translate(btVector3(0, vertical_offset, 0)); - } - else - { - Log::warn("overworld", "Invalid position after rescue for kart %s " - "on track %s.", (kart->getIdent().c_str()), - m_track->getIdent().c_str()); - } -} // moveKartAfterRescue - //----------------------------------------------------------------------------- /** Called when a mouse click happens. If the click happened while the mouse * was hovering on top of a challenge, the kart will be teleported to @@ -294,14 +213,19 @@ void OverWorld::onMouseClick(int x, int y) if(challenge) { + // Use the 'get closest start point' rescue function + // from WorldWithRank by setting the kart's position to + // be the location of the challenge bubble. AbstractKart* kart = getKart(0); - const btTransform& s = getClosestStartPoint(challenge->m_position.X, - challenge->m_position.Z); - const Vec3 &xyz = s.getOrigin(); - float angle = atan2(challenge->m_position.X - xyz[0], - challenge->m_position.Z - xyz[2]); - kart->setXYZ(xyz); - moveKartAfterRescue(kart, angle); + kart->setXYZ(challenge->m_position); + + unsigned int index = getRescuePositionIndex(kart); + btTransform s = getRescueTransform(index); + const btVector3 &xyz = s.getOrigin(); + float angle = atan2(challenge->m_position.X - xyz[0], + challenge->m_position.Z - xyz[2]); + s.setRotation( btQuaternion(btVector3(0.0f, 1.0f, 0.0f), angle) ); + moveKartTo(kart, s); return; } } // onMouseClick diff --git a/src/modes/overworld.hpp b/src/modes/overworld.hpp index 8c54f0350..a1dbdb752 100644 --- a/src/modes/overworld.hpp +++ b/src/modes/overworld.hpp @@ -20,7 +20,7 @@ #include -#include "modes/linear_world.hpp" +#include "modes/world_with_rank.hpp" #include "utils/aligned_array.hpp" #include "LinearMath/btTransform.h" @@ -32,7 +32,7 @@ * linear. * \ingroup modes */ -class OverWorld : public LinearWorld +class OverWorld : public WorldWithRank { protected: @@ -41,10 +41,6 @@ protected: bool m_return_to_garage; - void moveKartAfterRescue(AbstractKart* kart, float angle); - - btTransform getClosestStartPoint(float currentKart_x, float currentKart_z); - public: OverWorld(); virtual ~OverWorld(); @@ -52,7 +48,8 @@ public: static void enterOverWorld(); virtual void update(float delta) OVERRIDE; - + virtual void getKartsDisplayInfo( + std::vector *info) OVERRIDE; // ------------------------------------------------------------------------ /** Returns if this race mode has laps. */ virtual bool raceHasLaps() OVERRIDE { return false; } @@ -77,8 +74,6 @@ public: // ------------------------------------------------------------------------ void scheduleSelectKart() { m_return_to_garage = true; } // ------------------------------------------------------------------------ - virtual void moveKartAfterRescue(AbstractKart* kart) OVERRIDE; - // ------------------------------------------------------------------------ virtual void onMouseClick(int x, int y) OVERRIDE; }; diff --git a/src/modes/soccer_world.cpp b/src/modes/soccer_world.cpp index 22e4170f9..0d05351e6 100644 --- a/src/modes/soccer_world.cpp +++ b/src/modes/soccer_world.cpp @@ -191,88 +191,7 @@ void SoccerWorld::getKartsDisplayInfo( */ } // getKartsDisplayInfo -//----------------------------------------------------------------------------- -/** Moves a kart to its rescue position. - * \param kart The kart that was rescued. - */ -void SoccerWorld::moveKartAfterRescue(AbstractKart* kart) -{ - // find closest point to drop kart on - World *world = World::getWorld(); - const int start_spots_amount = world->getTrack()->getNumberOfStartPositions(); - assert(start_spots_amount > 0); - - float largest_accumulated_distance_found = -1; - int furthest_id_found = -1; - - const float kart_x = kart->getXYZ().getX(); - const float kart_z = kart->getXYZ().getZ(); - - for(int n=0; ngetTrack()->getStartTransform(n); - const Vec3 &v=s.getOrigin(); - float accumulatedDistance = .0f; - bool spawnPointClear = true; - - for(unsigned int k=0; kgetKart(k); - const float currentKart_x = currentKart->getXYZ().getX(); - const float currentKartk_z = currentKart->getXYZ().getZ(); - - if(kart_x!=currentKart_x && kart_z !=currentKartk_z) - { - float absDistance = fabs(currentKart_x - v.getX()) + - fabs(currentKartk_z - v.getZ()); - if(absDistance < CLEAR_SPAWN_RANGE) - { - spawnPointClear = false; - break; - } - accumulatedDistance += absDistance; - } - } - - if(largest_accumulated_distance_found < accumulatedDistance && spawnPointClear) - { - furthest_id_found = n; - largest_accumulated_distance_found = accumulatedDistance; - } - } - - assert(furthest_id_found != -1); - const btTransform &s = world->getTrack()->getStartTransform(furthest_id_found); - const Vec3 &xyz = s.getOrigin(); - kart->setXYZ(xyz); - kart->setRotation(s.getRotation()); - - //position kart from same height as in World::resetAllKarts - btTransform pos; - pos.setOrigin(kart->getXYZ()+btVector3(0, 0.5f*kart->getKartHeight(), 0.0f)); - pos.setRotation( btQuaternion(btVector3(0.0f, 1.0f, 0.0f), 0 /* angle */) ); - - kart->getBody()->setCenterOfMassTransform(pos); - - //project kart to surface of track - bool kart_over_ground = m_track->findGround(kart); - - if (kart_over_ground) - { - //add vertical offset so that the kart starts off above the track - float vertical_offset = kart->getKartProperties()->getVertRescueOffset() * - kart->getKartHeight(); - kart->getBody()->translate(btVector3(0, vertical_offset, 0)); - } - else - { - fprintf(stderr, "WARNING: invalid position after rescue for kart %s on track %s.\n", - (kart->getIdent().c_str()), m_track->getIdent().c_str()); - } -} // moveKartAfterRescue - +// ---------------------------------------------------------------------------- /** Set position and team for the karts */ void SoccerWorld::initKartList() { diff --git a/src/modes/soccer_world.hpp b/src/modes/soccer_world.hpp index 06aa1bcf1..591c0659a 100644 --- a/src/modes/soccer_world.hpp +++ b/src/modes/soccer_world.hpp @@ -64,7 +64,6 @@ public: virtual void getKartsDisplayInfo( std::vector *info); virtual bool raceHasLaps(){ return false; } - virtual void moveKartAfterRescue(AbstractKart* kart); virtual const std::string& getIdent() const; diff --git a/src/modes/three_strikes_battle.cpp b/src/modes/three_strikes_battle.cpp index 0da54b42b..023bb4c3f 100644 --- a/src/modes/three_strikes_battle.cpp +++ b/src/modes/three_strikes_battle.cpp @@ -1,3 +1,5 @@ + + // SuperTuxKart - a fun racing game with go-kart // Copyright (C) 2006 SuperTuxKart-Team // @@ -477,83 +479,52 @@ void ThreeStrikesBattle::getKartsDisplayInfo( } // getKartsDisplayInfo //----------------------------------------------------------------------------- -/** Moves a kart to its rescue position. - * \param kart The kart that was rescued. +/** Determines the rescue position for a kart. The rescue position is the + * start position which is has the biggest accumulated distance to all other + * karts, and which has no other kart very close. The latter avoids dropping + * a kart on top of another kart. + * \param kart The kart that is going to be rescued. + * \returns The index of the start position to which the rescued kart + * should be moved to. */ -void ThreeStrikesBattle::moveKartAfterRescue(AbstractKart* kart) + +unsigned int ThreeStrikesBattle::getRescuePositionIndex(AbstractKart *kart) { - // find closest point to drop kart on - World *world = World::getWorld(); - const int start_spots_amount = world->getTrack()->getNumberOfStartPositions(); + const int start_spots_amount = getTrack()->getNumberOfStartPositions(); assert(start_spots_amount > 0); float largest_accumulated_distance_found = -1; - int furthest_id_found = -1; - - const float kart_x = kart->getXYZ().getX(); - const float kart_z = kart->getXYZ().getZ(); + int furthest_id_found = -1; for(int n=0; ngetTrack()->getStartTransform(n); + const btTransform &s = getTrack()->getStartTransform(n); const Vec3 &v=s.getOrigin(); - float accumulatedDistance = .0f; - bool spawnPointClear = true; + float accumulated_distance = .0f; + bool spawn_point_clear = true; for(unsigned int k=0; kgetKart(k); - const float currentKart_x = currentKart->getXYZ().getX(); - const float currentKartk_z = currentKart->getXYZ().getZ(); - - if(kart_x!=currentKart_x && kart_z !=currentKartk_z) + if(kart->getWorldKartId()==k) continue; + float abs_distance2 = (getKart(k)->getXYZ()-v).length2_2d(); + const float CLEAR_SPAWN_RANGE2 = 5*5; + if( abs_distance2 < CLEAR_SPAWN_RANGE2) { - float absDistance = fabs(currentKart_x - v.getX()) + - fabs(currentKartk_z - v.getZ()); - if(absDistance < CLEAR_SPAWN_RANGE) - { - spawnPointClear = false; - break; - } - accumulatedDistance += absDistance; + spawn_point_clear = false; + break; } + accumulated_distance += sqrt(abs_distance2); } - if(largest_accumulated_distance_found < accumulatedDistance && spawnPointClear) + if(accumulated_distance > largest_accumulated_distance_found && + spawn_point_clear) { furthest_id_found = n; - largest_accumulated_distance_found = accumulatedDistance; + largest_accumulated_distance_found = accumulated_distance; } } assert(furthest_id_found != -1); - const btTransform &s = world->getTrack()->getStartTransform(furthest_id_found); - const Vec3 &xyz = s.getOrigin(); - kart->setXYZ(xyz); - kart->setRotation(s.getRotation()); + return furthest_id_found; +} // getRescuePositionIndex - //position kart from same height as in World::resetAllKarts - btTransform pos; - pos.setOrigin(kart->getXYZ()+btVector3(0, 0.5f*kart->getKartHeight(), 0.0f)); - pos.setRotation( btQuaternion(btVector3(0.0f, 1.0f, 0.0f), 0 /* angle */) ); - - kart->getBody()->setCenterOfMassTransform(pos); - - //project kart to surface of track - bool kart_over_ground = m_track->findGround(kart); - - if (kart_over_ground) - { - //add vertical offset so that the kart starts off above the track - float vertical_offset = kart->getKartProperties()->getVertRescueOffset() * - kart->getKartHeight(); - kart->getBody()->translate(btVector3(0, vertical_offset, 0)); - } - else - { - fprintf(stderr, "WARNING: invalid position after rescue for kart %s on track %s.\n", - (kart->getIdent().c_str()), m_track->getIdent().c_str()); - } -} // moveKartAfterRescue diff --git a/src/modes/three_strikes_battle.hpp b/src/modes/three_strikes_battle.hpp index 276dcc468..7cb8c8eb3 100644 --- a/src/modes/three_strikes_battle.hpp +++ b/src/modes/three_strikes_battle.hpp @@ -16,8 +16,8 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -#ifndef THREE_STRIKES_HPP -#define THREE_STRIKES_HPP +#ifndef THREE_STRIKES_BATTLE_HPP +#define THREE_STRIKES_BATTLE_HPP #include "modes/world_with_rank.hpp" @@ -28,8 +28,6 @@ #include -#define CLEAR_SPAWN_RANGE 5 - class PhysicalObject; /** @@ -99,7 +97,7 @@ public: virtual void getKartsDisplayInfo( std::vector *info); virtual bool raceHasLaps(){ return false; } - virtual void moveKartAfterRescue(AbstractKart* kart); + virtual unsigned int getRescuePositionIndex(AbstractKart *kart); virtual const std::string& getIdent() const; diff --git a/src/modes/tutorial_world.cpp b/src/modes/tutorial_world.cpp index 2f89f247a..70ddabad8 100644 --- a/src/modes/tutorial_world.cpp +++ b/src/modes/tutorial_world.cpp @@ -7,88 +7,4 @@ TutorialWorld::TutorialWorld() { m_stop_music_when_dialog_open = false; -} - -// ----------------------------------------------------------------------------- - -void TutorialWorld::moveKartAfterRescue(AbstractKart* kart) -{ - float angle = 0; - - // find closest point to drop kart on - World *world = World::getWorld(); - const int start_spots_amount = - world->getTrack()->getNumberOfStartPositions(); - assert(start_spots_amount > 0); - - const float currentKart_x = kart->getXYZ().getX(); - const float currentKart_z = kart->getXYZ().getZ(); - - const btTransform& s = getClosestStartPoint(currentKart_x, currentKart_z); - const Vec3 &xyz = s.getOrigin(); - kart->setXYZ(xyz); - kart->setRotation(s.getRotation()); - - //position kart from same height as in World::resetAllKarts - btTransform pos; - pos.setOrigin( kart->getXYZ() - +btVector3(0, 0.5f*kart->getKartHeight(), 0.0f)); - pos.setRotation( btQuaternion(btVector3(0.0f, 1.0f, 0.0f), angle) ); - - kart->getBody()->setCenterOfMassTransform(pos); - - //project kart to surface of track - bool kart_over_ground = m_track->findGround(kart); - - if (kart_over_ground) - { - //add vertical offset so that the kart starts off above the track - float vertical_offset = - kart->getKartProperties()->getVertRescueOffset() - * kart->getKartHeight(); - kart->getBody()->translate(btVector3(0, vertical_offset, 0)); - } - else - { - fprintf(stderr, "WARNING: invalid position after rescue for kart %s" - "on track %s.\n", - (kart->getIdent().c_str()), m_track->getIdent().c_str()); - } - -} // moveKartAfterRescue - -// ----------------------------------------------------------------------------- - -btTransform TutorialWorld::getClosestStartPoint(float currentKart_x, - float currentKart_z) -{ - // find closest point to drop kart on - World *world = World::getWorld(); - const int start_spots_amount = - world->getTrack()->getNumberOfStartPositions(); - assert(start_spots_amount > 0); - - - int closest_id = -1; - float closest_distance = 999999999.0f; - - for (int n=0; ngetTrack()->getStartTransform(n); - const Vec3 &v = s.getOrigin(); - - float absDistance = fabs(currentKart_x - v.getX()) + - fabs(currentKart_z - v.getZ()); - - if (absDistance < closest_distance) - { - closest_distance = absDistance; - closest_id = n; - } - } - - assert(closest_id != -1); - return world->getTrack()->getStartTransform(closest_id); -} // getClosestStartPoint +} // TutorialWorld \ No newline at end of file diff --git a/src/modes/tutorial_world.hpp b/src/modes/tutorial_world.hpp index 35be6fea9..5c2b3b2a1 100644 --- a/src/modes/tutorial_world.hpp +++ b/src/modes/tutorial_world.hpp @@ -6,13 +6,32 @@ class TutorialWorld : public StandardRace { -private: - btTransform getClosestStartPoint(float currentKart_x, float currentKart_z); public: TutorialWorld(); + virtual unsigned int getNumberOfRescuePositions() const OVERRIDE + { + // Don't use LinearWorld's function, but WorldWithRank, since the + // latter is based on rescuing to start positions + return WorldWithRank::getNumberOfRescuePositions(); + } + // ------------------------------------------------------------------------ + /** Determines the rescue position index of the specified kart. */ + virtual unsigned int getRescuePositionIndex(AbstractKart *kart) OVERRIDE + { + // Don't use LinearWorld's function, but WorldWithRank, since the + // latter is based on rescuing to start positions + return WorldWithRank::getRescuePositionIndex(kart); + } + // ------------------------------------------------------------------------ + /** Returns the bullet transformation for the specified rescue index. */ + virtual btTransform getRescueTransform(unsigned int index) const OVERRIDE + { + // Don't use LinearWorld's function, but WorldWithRank, since the + // latter is based on rescuing to start positions + return WorldWithRank::getRescueTransform(index); + } - virtual void moveKartAfterRescue(AbstractKart* kart) OVERRIDE; -}; +}; // class TutorialWorld #endif diff --git a/src/modes/world.cpp b/src/modes/world.cpp index 427a27caf..92e76e05f 100644 --- a/src/modes/world.cpp +++ b/src/modes/world.cpp @@ -79,7 +79,22 @@ World* World::m_world = NULL; * of all karts is set (i.e. in a normal race the arrival time for karts * will be estimated), highscore is updated, and the race result gui * is being displayed. + * Rescuing is handled via the three functions: + * getNumberOfRescuePositions() - which returns the number of rescue + * positions defined. + * getRescuePositionIndex(AbstractKart *kart) - which determines the + * index of the rescue position to be used for the given kart. + * getRescueTransform(unsigned int index) - which returns the transform + * (i.e. position and rotation) for the specified rescue + * position. + * This allows the world class to do some tests to make sure all rescue + * positions are valid (when started with --track-debug). It tries to + * place all karts on all rescue positions. If there are any problems + * (e.g. a rescue position not over terrain (perhaps because it is too + * low); or the rescue position is on a texture which will immediately + * trigger another rescue), a warning message will be printed. */ + //----------------------------------------------------------------------------- /** Constructor. Note that in the constructor it is not possible to call any * functions that use World::getWorld(), since this is only defined @@ -320,7 +335,7 @@ Controller* World::loadAIController(AbstractKart *kart) controller = new SkiddingAI(kart); break; default: - fprintf(stderr, "Warning: Unknown robot, using default.\n"); + Log::warn("World", "Unknown AI, using default."); controller = new SkiddingAI(kart); break; } @@ -471,65 +486,31 @@ void World::resetAllKarts() // If track checking is requested, check all rescue positions if // they are heigh enough. - if(race_manager->getMinorMode()!=RaceManager::MINOR_MODE_3_STRIKES && - UserConfigParams::m_track_debug) + if(UserConfigParams::m_track_debug) { - Vec3 eps = Vec3(0,1.5f*m_karts[0]->getKartHeight(),0); - for(unsigned int quad=0; quadgetNumNodes(); quad++) - { - const Quad &q = QuadGraph::get()->getQuadOfNode(quad); - const Vec3 center = q.getCenter(); - // We have to test for all karts, since the karts have different - // heights and so things might change from kart to kart. - for(unsigned int kart_id=0; kart_idsetXYZ(center); - - btQuaternion heading(btVector3(0.0f, 1.0f, 0.0f), - m_track->getAngle(quad) ); - kart->setRotation(heading); - - btTransform pos; - pos.setOrigin(center+eps); - pos.setRotation(btQuaternion(btVector3(0.0f, 1.0f, 0.0f), - m_track->getAngle(quad)) ); - kart->getBody()->setCenterOfMassTransform(pos); - - bool kart_over_ground = m_track->findGround(kart); - if(kart_over_ground) - { - const Vec3 &xyz = kart->getTrans().getOrigin() - + Vec3(0,0.3f,0); - if(dynamic_cast(kart)) - dynamic_cast(kart)->getTerrainInfo() - ->update(xyz); - const Material *material = kart->getMaterial(); - if(!material || material->isDriveReset()) - kart_over_ground = false; - } - if(!kart_over_ground) - { - printf("Kart '%s' not over quad '%d'\n", - kart->getIdent().c_str(), quad); - printf("Center point: %f %f %f\n", - center.getX(), center.getY(), center.getZ()); - - } - } // for kart_idreset(); - } + } // for kart_idgetIdent().c_str()); + Log::error("World", + "No valid starting position for kart %d on track %s.", + (int)(i-m_karts.begin()), m_track->getIdent().c_str()); if (UserConfigParams::m_artist_debug_mode) { - fprintf(stderr, "Activating fly mode.\n"); + Log::warn("World", "Activating fly mode."); (*i)->flyUp(); continue; } @@ -598,14 +578,14 @@ void World::resetAllKarts() &normal); if(!material) { - fprintf(stderr, - "ERROR: no valid starting position for " - "kart %d on track %s.\n", - (int)(i-m_karts.begin()), - m_track->getIdent().c_str()); + Log::error("World", + "No valid starting position for kart %d " + "on track %s.", + (int)(i-m_karts.begin()), + m_track->getIdent().c_str()); if (UserConfigParams::m_artist_debug_mode) { - fprintf(stderr, "Activating fly mode.\n"); + Log::warn("World", "Activating fly mode."); (*i)->flyUp(); continue; } @@ -637,6 +617,44 @@ void World::resetAllKarts() } } // resetAllKarts +// ---------------------------------------------------------------------------- +/** Places a kart that is rescued. It calls getRescuePositionIndex to find + * to which rescue position the kart should be moved, then getRescueTransform + * to get the position and rotation of this rescue position, and then moves + * the kart. + * \param kart The kart that is rescued. + */ +void World::moveKartAfterRescue(AbstractKart* kart) +{ + unsigned int index = getRescuePositionIndex(kart); + btTransform t = getRescueTransform(index); + moveKartTo(kart, t); +} // moveKartAfterRescue + +// ---------------------------------------------------------------------------- +/** Places the kart at a given position and rotation. + * \param kart The kart to be moved. + * \param transform + */ +void World::moveKartTo(AbstractKart* kart, const btTransform &transform) +{ + btTransform pos(transform); + + // Move the kart + Vec3 xyz = pos.getOrigin() + btVector3(0, 0.5f*kart->getKartHeight(),0.0f); + + pos.setOrigin(xyz); + kart->setXYZ(xyz); + kart->setRotation(pos.getRotation()); + + kart->getBody()->setCenterOfMassTransform(pos); + + // Project kart to surface of track + // This will set the physics transform + m_track->findGround(kart); + +} // moveKartTo + // ---------------------------------------------------------------------------- void World::schedulePause(Phase phase) { @@ -730,13 +748,15 @@ void World::updateWorld(float dt) InputDevice* device = input_manager->getDeviceList()->getKeyboard(0); // Create player and associate player with keyboard - StateManager::get()->createActivePlayer(unlock_manager->getCurrentPlayer(), - device); + StateManager::get() + ->createActivePlayer(unlock_manager->getCurrentPlayer(), + device); - if (kart_properties_manager->getKart(UserConfigParams::m_default_kart) == NULL) + if (!kart_properties_manager->getKart(UserConfigParams::m_default_kart)) { - fprintf(stderr, "[MainMenuScreen] WARNING: cannot find kart '%s', will revert to default\n", - UserConfigParams::m_default_kart.c_str()); + Log::warn("World", + "Cannot find kart '%s', will revert to default.", + UserConfigParams::m_default_kart.c_str()); UserConfigParams::m_default_kart.revertToDefaults(); } race_manager->setLocalKartInfo(0, UserConfigParams::m_default_kart); @@ -912,11 +932,11 @@ void World::updateHighscores(int* best_highscore_rank, int* best_finish_time, // the kart location data is wrong #ifdef DEBUG - fprintf(stderr, "Error, incorrect kart positions:\n"); + Log::error("World", "Incorrect kart positions:"); for (unsigned int i=0; igetPosition()); + Log::error("World", "i=%d position %d.",i, + m_karts[i]->getPosition()); } #endif continue; diff --git a/src/modes/world.hpp b/src/modes/world.hpp index 838723669..c981c960c 100644 --- a/src/modes/world.hpp +++ b/src/modes/world.hpp @@ -33,6 +33,8 @@ #include "states_screens/state_manager.hpp" #include "utils/random_generator.hpp" +#include "LinearMath/btTransform.h" + class AbstractKart; class btRigidBody; class Controller; @@ -156,6 +158,7 @@ protected: virtual void update(float dt); virtual void createRaceGUI(); void updateTrack(float dt); + void moveKartTo(AbstractKart* kart, const btTransform &t); // ------------------------------------------------------------------------ /** Used for AI karts that are still racing when all player kart finished. * Generally it should estimate the arrival time for those karts, but as @@ -192,13 +195,19 @@ public: /** Each game mode should have a unique identifier. Override * this method in child classes to provide it. */ - virtual const std::string& - getIdent() const = 0; + virtual const std::string& getIdent() const = 0; // ------------------------------------------------------------------------ - /** Since each mode will have a different way of deciding where a rescued - * kart is dropped, this method will be called and each mode can implement - * it. */ - virtual void moveKartAfterRescue(AbstractKart* kart) = 0; + /** Returns the number of rescue positions on a given track and game + * mode. */ + virtual unsigned int getNumberOfRescuePositions() const OVERRIDE = 0; + // ------------------------------------------------------------------------ + /** Determines the rescue position index of the specified kart. */ + virtual unsigned int getRescuePositionIndex(AbstractKart *kart) = 0; + // ------------------------------------------------------------------------ + /** Returns the bullet transformation for the specified rescue index. */ + virtual btTransform getRescueTransform(unsigned int index) const = 0; + // ------------------------------------------------------------------------ + void moveKartAfterRescue(AbstractKart* kart); // ------------------------------------------------------------------------ /** Called when it is needed to know whether this kind of race involves * counting laps. */ diff --git a/src/modes/world_with_rank.cpp b/src/modes/world_with_rank.cpp index 47f0aee95..e4668ef41 100644 --- a/src/modes/world_with_rank.cpp +++ b/src/modes/world_with_rank.cpp @@ -18,7 +18,9 @@ #include "modes/world_with_rank.hpp" #include "karts/abstract_kart.hpp" +#include "karts/kart_properties.hpp" #include "race/history.hpp" +#include "tracks/track.hpp" #include @@ -120,3 +122,53 @@ void WorldWithRank::endSetKartPositions() } // endSetKartPositions +//----------------------------------------------------------------------------- +/** WorldWithRank uses the start position as rescue positions. So return + * the number of start positions. + */ +unsigned int WorldWithRank::getNumberOfRescuePositions() const +{ + return getTrack()->getNumberOfStartPositions(); +} // getNumberOfRescuePositions + +// ---------------------------------------------------------------------------- +/** Finds the starting position which is closest to the kart. + * \param kart The kart for which a rescue position needs to be determined. + */ +unsigned int WorldWithRank::getRescuePositionIndex(AbstractKart *kart) +{ + // find closest point to drop kart on + const int start_spots_amount = getNumberOfRescuePositions(); + assert(start_spots_amount > 0); + + int closest_id = -1; + float closest_distance = 999999999.0f; + + for (int n=0; ngetStartTransform(n); + const Vec3 &v = s.getOrigin(); + + float abs_distance = (v - kart->getXYZ()).length(); + + if (abs_distance < closest_distance) + { + closest_distance = abs_distance; + closest_id = n; + } + } + + assert(closest_id != -1); + return closest_id; +} // getRescuePositionIndex + +// ---------------------------------------------------------------------------- +/** Returns the start transform with the give index. + * \param rescue_pos Index of the start position to be returned. + * \returns The transform of the corresponding start position. + */ +btTransform WorldWithRank::getRescueTransform(unsigned int rescue_pos) const +{ + return getTrack()->getStartTransform(rescue_pos); +} // getRescueTransform + diff --git a/src/modes/world_with_rank.hpp b/src/modes/world_with_rank.hpp index a0995c89c..79bc2f3b1 100644 --- a/src/modes/world_with_rank.hpp +++ b/src/modes/world_with_rank.hpp @@ -28,7 +28,10 @@ class AbstractKart; * A WorldWithRank is a world where the karts are ranked. This is the base * class for races and battle modes - all of which rank the kart. * A class using this as a subclass must call setKartPosition(kart id, position) - * and this class is used to access the ranks from other objects. + * and this class is used to access the ranks from other objects. This class + * adds a convenient rescue implementation: a kart is rescued to the closest + * start point. This is useful for battle, soccer, ... modes. Linear world + * defines its own rescue functions and will overwrite this. * \ingroup modes */ class WorldWithRank : public World @@ -51,6 +54,8 @@ protected: bool m_position_setting_initialised; #endif + unsigned int WorldWithRank::getClosestStartPoint(AbstractKart *kart); + public: WorldWithRank() : World() {} /** call just after instanciating. can't be moved to the contructor as child @@ -64,8 +69,13 @@ public: bool setKartPosition(unsigned int kart_id, unsigned int position); void endSetKartPositions(); - AbstractKart* getKartAtPosition(unsigned int p) const; + + virtual unsigned int getNumberOfRescuePositions() const OVERRIDE; + virtual unsigned int getRescuePositionIndex(AbstractKart *kart) OVERRIDE; + virtual btTransform getRescueTransform(unsigned int index) const OVERRIDE; + + }; // WorldWithRank #endif