Added new smart rescue

git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@9807 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
auria
2011-09-11 23:59:49 +00:00
parent ee7b178dce
commit 2311b11b90
16 changed files with 137 additions and 45 deletions

View File

@@ -251,7 +251,7 @@ void Powerup::use()
}
m_sound_use->play();
projectile_manager->newProjectile(m_owner, m_type);
projectile_manager->newProjectile(m_owner, world->getTrack(), m_type);
break ;
case PowerupManager::POWERUP_SWATTER:

View File

@@ -152,16 +152,16 @@ void ProjectileManager::updateClient(float dt)
} // updateClient
// -----------------------------------------------------------------------------
Flyable *ProjectileManager::newProjectile(Kart *kart,
Flyable *ProjectileManager::newProjectile(Kart *kart, Track* track,
PowerupManager::PowerupType type)
{
Flyable *f;
switch(type)
{
case PowerupManager::POWERUP_BOWLING: f = new Bowling(kart); break;
case PowerupManager::POWERUP_PLUNGER: f = new Plunger(kart); break;
case PowerupManager::POWERUP_CAKE: f = new Cake(kart); break;
case PowerupManager::POWERUP_RUBBERBALL: f = new RubberBall(kart);break;
case PowerupManager::POWERUP_BOWLING: f = new Bowling(kart); break;
case PowerupManager::POWERUP_PLUNGER: f = new Plunger(kart); break;
case PowerupManager::POWERUP_CAKE: f = new Cake(kart); break;
case PowerupManager::POWERUP_RUBBERBALL: f = new RubberBall(kart, track); break;
default: return NULL;
}
m_active_projectiles.push_back(f);

View File

@@ -35,6 +35,7 @@ class Vec3;
class Kart;
class HitEffect;
class Flyable;
class Track;
/**
* \ingroup items
@@ -61,7 +62,7 @@ public:
void loadData ();
void cleanup ();
void update (float dt);
Flyable* newProjectile (Kart *kart,
Flyable* newProjectile (Kart *kart, Track* track,
PowerupManager::PowerupType type);
void Deactivate (Flyable *p) {}
void removeTextures ();

View File

@@ -34,10 +34,12 @@ float RubberBall::m_st_squash_slowdown;
float RubberBall::m_st_target_distance;
int RubberBall::m_next_id = 0;
RubberBall::RubberBall(Kart *kart)
RubberBall::RubberBall(Kart *kart, Track* track)
: Flyable(kart, PowerupManager::POWERUP_RUBBERBALL, 0.0f /* mass */),
TrackSector()
{
m_track = track;
// For debugging purpose: pre-fix each debugging line with the id of
// the ball so that it's easy to collect all debug output for one
// particular ball only.
@@ -65,7 +67,7 @@ RubberBall::RubberBall(Kart *kart)
computeTarget();
// initialises the current graph node
TrackSector::update(getXYZ());
TrackSector::update(getXYZ(), kart, track);
initializeControlPoints(m_owner->getXYZ());
// At the start the ball aims at quads till it gets close enough to the
@@ -320,7 +322,7 @@ bool RubberBall::updateAndDelete(float dt)
next_xyz.setY(new_y);
// Determine new distance along track
TrackSector::update(next_xyz);
TrackSector::update(next_xyz, m_owner, m_track);
// Ball squashing:
// ===============

View File

@@ -121,6 +121,8 @@ private:
/** Sound effect to be played when a ball hits a kart. */
SFXBase *m_hit_sfx;
Track *m_track;
void computeTarget();
void checkDistanceToTarget();
@@ -132,7 +134,7 @@ private:
void initializeControlPoints(const Vec3 &xyz);
float getMaxTerrainHeight() const;
public:
RubberBall (Kart* kart);
RubberBall (Kart* kart, Track* track);
virtual ~RubberBall();
static void init(const XMLNode &node, scene::IMesh *bowling);
virtual bool updateAndDelete(float dt);

View File

@@ -62,7 +62,7 @@ void LinearWorld::init()
for(unsigned int n=0; n<kart_amount; n++)
{
KartInfo info;
info.getSector()->update(m_karts[n]->getXYZ());
info.getSector()->update(m_karts[n]->getXYZ(), m_karts[n], m_track);
m_kart_info.push_back(info);
} // next kart
@@ -92,7 +92,7 @@ void LinearWorld::restartRace()
for(unsigned int i=0; i<kart_amount; i++)
{
m_kart_info[i].reset();
m_kart_info[i].getSector()->update(m_karts[i]->getXYZ());
m_kart_info[i].getSector()->update(m_karts[i]->getXYZ(), m_karts[i], m_track);
} // next kart
// First all kart infos must be updated before the kart position can be
@@ -149,7 +149,7 @@ void LinearWorld::update(float dt)
// Nothing to do for karts that are currently being rescued or eliminated
if(kart->playingEmergencyAnimation()) continue;
kart_info.getSector()->update(kart->getXYZ());
kart_info.getSector()->update(kart->getXYZ(), kart, m_track);
} // for n
// Update all positions. This must be done after _all_ karts have

View File

@@ -24,6 +24,7 @@
#include "io/xml_node.hpp"
#include "modes/linear_world.hpp"
#include "race/race_manager.hpp"
#include "tracks/check_manager.hpp"
#include "tracks/track.hpp"
/** Constructor for a lap line.
@@ -72,5 +73,16 @@ bool CheckLap::isTriggered(const Vec3 &old_pos, const Vec3 &new_pos, int indx)
m_previous_distance[indx], current_distance);
}
m_previous_distance[indx] = current_distance;
// If a lap was triggered, reset all visit flags
if (result)
{
CheckManager* cm = World::getWorld()->getTrack()->getCheckManager();
for (int n=0; n<cm->getCheckStructureCount(); n++)
{
cm->getCheckStructure(n)->resetVisits();
}
}
return result;
} // isTriggered

View File

@@ -77,6 +77,8 @@ void CheckStructure::reset(const Track &track)
{
m_previous_position.clear();
m_is_active.clear();
m_was_visited.clear();
World *world = World::getWorld();
for(unsigned int i=0; i<world->getNumKarts(); i++)
{
@@ -85,6 +87,7 @@ void CheckStructure::reset(const Track &track)
// Activate all checkline
m_is_active.push_back(m_active_at_reset);
m_was_visited.push_back(false);
} // for i<getNumKarts
} // reset
@@ -173,7 +176,6 @@ void CheckStructure::changeStatus(const std::vector<int> indices,
}
} // for i<indices.size()
/*
printf("--------\n");
for (int n=0; n<m_check_manager->getCheckStructureCount(); n++)
@@ -186,6 +188,7 @@ void CheckStructure::changeStatus(const std::vector<int> indices,
}
*/
} //changeStatus
// ----------------------------------------------------------------------------
@@ -194,6 +197,8 @@ void CheckStructure::changeStatus(const std::vector<int> indices,
*/
void CheckStructure::trigger(unsigned int kart_index)
{
m_was_visited[kart_index] = true;
switch(m_check_type)
{
case CT_NEW_LAP :

View File

@@ -69,6 +69,8 @@ protected:
AlignedArray<Vec3> m_previous_position;
/** Stores if this check structure is active (for a given kart). */
std::vector<bool> m_is_active;
/** If this check structure was triggered during this lap (for each kart) */
std::vector<bool> m_was_visited;
/** True if this check structure should be activated at a reset. */
bool m_active_at_reset;
@@ -120,6 +122,21 @@ public:
/** Returns the type of this check structure. */
CheckType getType() const { return m_check_type; }
bool wasVisitedForKart(int kart_id)
{
assert(kart_id < (int)m_was_visited.size());
assert(kart_id >= 0);
return m_was_visited[kart_id];
}
void resetVisits()
{
for (unsigned int n=0; n<m_was_visited.size(); n++)
{
m_was_visited[n] = false;
}
}
}; // CheckStructure
#endif

View File

@@ -219,7 +219,7 @@ float GraphNode::getDistance2FromPoint(const Vec3 &xyz)
// ----------------------------------------------------------------------------
void GraphNode::setChecklineRequirements(const std::set<int>& r)
void GraphNode::setChecklineRequirements(int latest_checkline)
{
m_checkline_requirements.push_back(r);
m_checkline_requirements.push_back(latest_checkline);
}

View File

@@ -21,7 +21,6 @@
#define HEADER_GRAPH_NODE_HPP
#include <vector>
#include <set>
#include <vector2d.h>
#include <dimension2d.h>
@@ -104,7 +103,7 @@ class GraphNode
* this node (there is a possibility of more than one set because of
* alternate ways)
*/
std::vector< std::set<int> > m_checkline_requirements;
std::vector< int > m_checkline_requirements;
public:
/** Keep a shared pointer so that some asserts and tests can be
@@ -197,7 +196,9 @@ public:
}
// ------------------------------------------------------------------------
void setChecklineRequirements(const std::set<int>& r);
void setChecklineRequirements(int latest_checkline);
const std::vector<int>& getChecklineRequirements() const { return m_checkline_requirements; }
}; // GraphNode
#endif

View File

@@ -189,7 +189,7 @@ void QuadGraph::load(const std::string &filename)
* Finds which checklines must be visited before driving on this quad
* (useful for rescue)
*/
void QuadGraph::setChecklineRequirements(GraphNode* node, std::set<int> checklines)
void QuadGraph::setChecklineRequirements(GraphNode* node, int latest_checkline)
{
Track* t = World::getWorld()->getTrack();
CheckManager* cm = t->getCheckManager();
@@ -202,7 +202,7 @@ void QuadGraph::setChecklineRequirements(GraphNode* node, std::set<int> checklin
// warp-around
if (succ_id == 0) break;
std::set<int> these_checklines = checklines;
int new_latest_checkline = latest_checkline;
GraphNode* succ = m_all_nodes[succ_id];
for (int i=0; i<cm->getCheckStructureCount(); i++)
@@ -214,12 +214,14 @@ void QuadGraph::setChecklineRequirements(GraphNode* node, std::set<int> checklin
if (c->isTriggered(node->getCenter(), succ->getCenter(), 0 /* kart id */))
{
//printf("* Check %i is triggerred when going from %i to %i\n", i, node->getIndex(), succ_id);
these_checklines.insert(i);
new_latest_checkline = i;
break;
}
}
/*
printf("Quad %i : checkline %i\n", succ_id, new_latest_checkline);
printf("Quad %i :\n", succ_id);
for (std::set<int>::iterator it = these_checklines.begin();it != these_checklines.end(); it++)
{
@@ -227,8 +229,10 @@ void QuadGraph::setChecklineRequirements(GraphNode* node, std::set<int> checklin
}
*/
succ->setChecklineRequirements(these_checklines);
setChecklineRequirements(succ, these_checklines);
if (new_latest_checkline != -1)
succ->setChecklineRequirements(new_latest_checkline);
setChecklineRequirements(succ, new_latest_checkline);
}
}

View File

@@ -79,7 +79,7 @@ private:
std::string m_quad_filename;
void setDefaultSuccessors();
void setChecklineRequirements(GraphNode* node, std::set<int> checklines);
void setChecklineRequirements(GraphNode* node, int latest_checkline);
void load (const std::string &filename);
void createMesh(bool show_invisible=true,
@@ -177,7 +177,7 @@ public:
void setChecklineRequirements()
{
setChecklineRequirements(m_all_nodes[0], std::set<int>());
setChecklineRequirements(m_all_nodes[0], -1);
}
}; // QuadGraph

View File

@@ -1447,7 +1447,7 @@ void Track::loadTrackModel(World* parent, unsigned int mode_id)
irr_driver->getSceneManager()->getMeshCache()->getMeshCount(),
irr_driver->getVideoDriver()->getTextureCount());
//QuadGraph::get()->setChecklineRequirements();
QuadGraph::get()->setChecklineRequirements();
} // loadTrackModel

View File

@@ -17,10 +17,13 @@
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "modes/world.hpp"
#include "tracks/check_manager.hpp"
#include "tracks/check_structure.hpp"
#include "tracks/track.hpp"
#include "tracks/track_sector.hpp"
#include "tracks/quad_graph.hpp"
// ----------------------------------------------------------------------------
/** Initialises the object, and sets the current graph node to be undefined.
*/
@@ -42,13 +45,26 @@ void TrackSector::reset()
* the specified point.
* \param xyz The new coordinates to search the graph node for.
*/
void TrackSector::update(const Vec3 &xyz)
void TrackSector::update(const Vec3 &xyz, Kart* kart, Track* track)
{
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;
int kart_id = -1;
World* world = World::getWorld();
for (unsigned int i=0; i<world->getNumKarts(); i++)
{
if (world->getKart(i) == kart)
{
kart_id = i;
break;
}
}
assert(kart_id != -1);
// 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)
@@ -57,9 +73,47 @@ void TrackSector::update(const Vec3 &xyz)
QuadGraph::get()->findOutOfRoadSector(xyz,
prev_sector);
}
else
m_last_valid_graph_node = m_current_graph_node;
if(m_current_graph_node != QuadGraph::UNKNOWN_SECTOR)
{
// keep the current quad as the latest valid one IF the player has one of the required checklines
const std::vector<int>& checkline_requirements =
QuadGraph::get()->getNode(m_current_graph_node).getChecklineRequirements();
//if (m_last_valid_graph_node != m_current_graph_node)
// printf("Checking quad %i, which has requirement %i\n", m_current_graph_node,
// checkline_requirements.size() == 0 ? -99 : checkline_requirements[0]);
CheckManager* cm = track->getCheckManager();
const unsigned int count = cm->getCheckStructureCount();
if (checkline_requirements.size() == 0)
{
//if (m_last_valid_graph_node != m_current_graph_node)
// printf("[1] m_last_valid_graph_node : %i\n", m_last_valid_graph_node);
m_last_valid_graph_node = m_current_graph_node;
}
else
{
for (unsigned int i=0; i<checkline_requirements.size(); i++)
{
//for (int k=0; k<cm->getCheckStructureCount(); k++)
// printf(" Check %i visited : %i\n", k, cm->getCheckStructure(k)->wasVisitedForKart(kart_id));
if (checkline_requirements[i] < (int)count &&
cm->getCheckStructure(checkline_requirements[i])->wasVisitedForKart(kart_id))
{
//if (m_last_valid_graph_node != m_current_graph_node)
// printf("[2] m_last_valid_graph_node : %i\n", m_last_valid_graph_node);
m_last_valid_graph_node = m_current_graph_node;
break;
}
}
}
}
// 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,
@@ -69,17 +123,8 @@ void TrackSector::update(const Vec3 &xyz)
// ----------------------------------------------------------------------------
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())
{
if (m_last_valid_graph_node != QuadGraph::UNKNOWN_SECTOR)
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

View File

@@ -22,6 +22,9 @@
#include "utils/vec3.hpp"
class Track;
class Kart;
/** 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).
@@ -55,7 +58,7 @@ public:
TrackSector();
void reset();
void rescue();
void update(const Vec3 &xyz);
void update(const Vec3 &xyz, Kart* kart, Track* track);
// ------------------------------------------------------------------------
/** Returns how far the the object is from the start line. */
float getDistanceFromStart() const { return m_current_track_coords.getZ();}