First playable version of battle AI
TODO: backwards firing better handling to obstacles ai karts number selection win/lose screen handling Please use a better navmesh to test
This commit is contained in:
parent
f4b723de82
commit
62f5be0d9d
@ -39,23 +39,24 @@ AIBaseController::AIBaseController(AbstractKart *kart,
|
||||
m_kart = kart;
|
||||
m_kart_length = m_kart->getKartLength();
|
||||
m_kart_width = m_kart->getKartWidth();
|
||||
m_ai_properties =
|
||||
m_kart->getKartProperties()->getAIPropertiesForDifficulty();
|
||||
|
||||
m_ai_properties = m_kart->getKartProperties()->getAIPropertiesForDifficulty();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void AIBaseController::reset()
|
||||
{
|
||||
m_stuck = false;
|
||||
m_collision_times.clear();
|
||||
} // reset
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void AIBaseController::update(float dt)
|
||||
{
|
||||
m_stuck = false;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** In debug mode when the user specified --ai-debug on the command line set
|
||||
* the name of the controller as on-screen text, so that the different AI
|
||||
@ -249,7 +250,6 @@ bool AIBaseController::doSkid(float steer_fraction)
|
||||
return fabsf(steer_fraction)>=m_ai_properties->m_skidding_threshold;
|
||||
} // doSkid
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** This is called when the kart crashed with the terrain. This subroutine
|
||||
* tries to detect if the AI is stuck by determining if a certain number
|
||||
@ -283,7 +283,6 @@ void AIBaseController::crashed(const Material *m)
|
||||
if(time - m_collision_times.back() < 0.2f)
|
||||
return;
|
||||
|
||||
|
||||
// Remove all outdated entries, i.e. entries that are older than the
|
||||
// collision time plus 1 second. Older entries must be deleted,
|
||||
// otherwise a collision that happened (say) 10 seconds ago could
|
||||
|
@ -22,7 +22,6 @@
|
||||
#include "karts/controller/controller.hpp"
|
||||
#include "states_screens/state_manager.hpp"
|
||||
|
||||
|
||||
class AIProperties;
|
||||
class LinearWorld;
|
||||
class ThreeStrikesBattle;
|
||||
@ -31,9 +30,12 @@ class BattleGraph;
|
||||
class Track;
|
||||
class Vec3;
|
||||
|
||||
/** A base class for all AI karts. This class basically provides some
|
||||
* common low level functions.
|
||||
* \ingroup controller
|
||||
*/
|
||||
class AIBaseController : public Controller
|
||||
{
|
||||
|
||||
private:
|
||||
/** Stores the last N times when a collision happened. This is used
|
||||
* to detect when the AI is stuck, i.e. N collisions happened in
|
||||
@ -44,7 +46,6 @@ private:
|
||||
* this kart is stuck and needs to be rescued. */
|
||||
bool m_stuck;
|
||||
|
||||
|
||||
protected:
|
||||
/** Length of the kart, storing it here saves many function calls. */
|
||||
float m_kart_length;
|
||||
@ -52,36 +53,12 @@ protected:
|
||||
/** Cache width of kart. */
|
||||
float m_kart_width;
|
||||
|
||||
|
||||
/** Keep a pointer to the track to reduce calls */
|
||||
Track *m_track;
|
||||
|
||||
|
||||
|
||||
/** A pointer to the AI properties for this kart. */
|
||||
const AIProperties *m_ai_properties;
|
||||
|
||||
<<<<<<< HEAD
|
||||
/** The current node the kart is on. This can be different from the value
|
||||
* in LinearWorld, since it takes the chosen path of the AI into account
|
||||
* (e.g. the closest point in LinearWorld might be on a branch not
|
||||
* chosen by the AI). */
|
||||
int m_track_node;
|
||||
|
||||
/** Which of the successors of a node was selected by the AI. */
|
||||
std::vector<int> m_successor_index;
|
||||
/** For each node in the graph this list contains the chosen next node.
|
||||
* For normal lap track without branches we always have
|
||||
* m_next_node_index[i] = (i+1) % size;
|
||||
* but if a branch is possible, the AI will select one option here.
|
||||
* If the node is not used, m_next_node_index will be -1. */
|
||||
std::vector<int> m_next_node_index;
|
||||
/** For each graph node this list contains a list of the next X
|
||||
* graph nodes. */
|
||||
std::vector<std::vector<int> > m_all_look_aheads;
|
||||
=======
|
||||
>>>>>>> origin/battleAI
|
||||
|
||||
static bool m_ai_debug;
|
||||
|
||||
virtual void update (float delta) ;
|
||||
@ -90,24 +67,21 @@ protected:
|
||||
float steerToPoint(const Vec3 &point);
|
||||
float normalizeAngle(float angle);
|
||||
virtual bool doSkid(float steer_fraction);
|
||||
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** This can be called to detect if the kart is stuck (i.e. repeatedly
|
||||
* hitting part of the track). */
|
||||
bool isStuck() const { return m_stuck; }
|
||||
|
||||
public:
|
||||
|
||||
AIBaseController(AbstractKart *kart,
|
||||
StateManager::ActivePlayer *player=NULL);
|
||||
virtual ~AIBaseController() {};
|
||||
virtual void reset();
|
||||
static void enableDebug() {m_ai_debug = true; }
|
||||
virtual bool disableSlipstreamBonus() const;
|
||||
|
||||
virtual void crashed(const Material *m);
|
||||
}; // AIBaseController
|
||||
|
||||
};
|
||||
#endif
|
||||
|
||||
/* EOF */
|
||||
|
@ -88,7 +88,7 @@ AIBaseLapController::AIBaseLapController(AbstractKart *kart,
|
||||
: AIBaseController(kart, player)
|
||||
{
|
||||
|
||||
if(race_manager->getMinorMode()!=RaceManager::MINOR_MODE_3_STRIKES &&
|
||||
if (race_manager->getMinorMode()!=RaceManager::MINOR_MODE_3_STRIKES &&
|
||||
race_manager->getMinorMode()!=RaceManager::MINOR_MODE_SOCCER)
|
||||
{
|
||||
m_world = dynamic_cast<LinearWorld*>(World::getWorld());
|
||||
@ -224,7 +224,6 @@ void AIBaseLapController::update(float dt)
|
||||
}
|
||||
} // update
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Returns the next sector of the given sector index. This is used
|
||||
* for branches in the quad graph to select which way the AI kart should
|
||||
@ -262,5 +261,3 @@ float AIBaseLapController::steerToAngle(const unsigned int sector,
|
||||
|
||||
return steer_angle;
|
||||
} // steerToAngle
|
||||
|
||||
|
||||
|
@ -33,10 +33,7 @@ class Vec3;
|
||||
*/
|
||||
class AIBaseLapController : public AIBaseController
|
||||
{
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
/** The current node the kart is on. This can be different from the value
|
||||
* in LinearWorld, since it takes the chosen path of the AI into account
|
||||
* (e.g. the closest point in LinearWorld might be on a branch not
|
||||
@ -65,14 +62,11 @@ protected:
|
||||
|
||||
float steerToAngle (const unsigned int sector, const float angle);
|
||||
|
||||
|
||||
void computePath();
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Nothing special to do when the race is finished. */
|
||||
virtual void raceFinished() {};
|
||||
|
||||
|
||||
public:
|
||||
AIBaseLapController(AbstractKart *kart,
|
||||
StateManager::ActivePlayer *player=NULL);
|
||||
@ -88,9 +82,6 @@ public:
|
||||
virtual bool isPlayerController() const { return false; }
|
||||
virtual void action(PlayerAction action, int value) {};
|
||||
virtual void skidBonusTriggered() {};
|
||||
|
||||
}; // AIBaseLapController
|
||||
|
||||
#endif
|
||||
|
||||
/* EOF */
|
||||
|
@ -45,6 +45,7 @@ protected:
|
||||
friend class AIBaseController;
|
||||
friend class AIBaseLapController;
|
||||
friend class SkiddingAI;
|
||||
friend class BattleAI;
|
||||
|
||||
/** Used to check that all values are defined in the xml file. */
|
||||
static float UNDEFINED;
|
||||
|
@ -18,16 +18,20 @@
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#define AI_DEBUG
|
||||
//#define AI_DEBUG
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
#include "karts/controller/battle_ai.hpp"
|
||||
|
||||
#ifdef AI_DEBUG
|
||||
# include "graphics/irr_driver.hpp"
|
||||
#endif
|
||||
//#ifdef AI_DEBUG
|
||||
#include "graphics/irr_driver.hpp"
|
||||
//#endif
|
||||
|
||||
#include "items/attachment.hpp"
|
||||
#include "items/item_manager.hpp"
|
||||
#include "items/powerup.hpp"
|
||||
#include "items/projectile_manager.hpp"
|
||||
#include "karts/abstract_kart.hpp"
|
||||
#include "karts/controller/kart_control.hpp"
|
||||
#include "karts/controller/player_controller.hpp"
|
||||
@ -40,16 +44,17 @@
|
||||
#include "modes/three_strikes_battle.hpp"
|
||||
#include "tracks/nav_poly.hpp"
|
||||
#include "tracks/navmesh.hpp"
|
||||
#include "utils/log.hpp"
|
||||
|
||||
#ifdef AI_DEBUG
|
||||
# include "irrlicht.h"
|
||||
using namespace irr;
|
||||
#include "irrlicht.h"
|
||||
using namespace irr;
|
||||
#endif
|
||||
|
||||
#if defined(WIN32) && !defined(__CYGWIN__) && !defined(__MINGW32__)
|
||||
# define isnan _isnan
|
||||
#define isnan _isnan
|
||||
#else
|
||||
# include <math.h>
|
||||
#include <math.h>
|
||||
#endif
|
||||
|
||||
#include <iostream>
|
||||
@ -61,19 +66,17 @@ BattleAI::BattleAI(AbstractKart *kart,
|
||||
|
||||
reset();
|
||||
|
||||
#ifdef AI_DEBUG
|
||||
|
||||
#ifdef AI_DEBUG
|
||||
video::SColor col_debug(128, 128,0,0);
|
||||
m_debug_sphere = irr_driver->addSphere(1.0f, col_debug);
|
||||
m_debug_sphere->setVisible(true);
|
||||
//m_item_sphere = irr_driver->addSphere(1.0f);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if(race_manager->getMinorMode()==RaceManager::MINOR_MODE_3_STRIKES)
|
||||
if (race_manager->getMinorMode() == RaceManager::MINOR_MODE_3_STRIKES)
|
||||
{
|
||||
m_world = dynamic_cast<ThreeStrikesBattle*>(World::getWorld());
|
||||
m_track = m_world->getTrack();
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -84,11 +87,13 @@ BattleAI::BattleAI(AbstractKart *kart,
|
||||
}
|
||||
|
||||
// Don't call our own setControllerName, since this will add a
|
||||
// billboard showing 'AIBaseController' to the kar.
|
||||
// billboard showing 'AIBaseController' to the kart.
|
||||
Controller::setControllerName("BattleAI");
|
||||
|
||||
} // BattleAI
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
BattleAI::~BattleAI()
|
||||
{
|
||||
#ifdef AI_DEBUG
|
||||
@ -102,12 +107,11 @@ BattleAI::~BattleAI()
|
||||
void BattleAI::reset()
|
||||
{
|
||||
m_current_node = BattleGraph::UNKNOWN_POLY;
|
||||
m_next_node = BattleGraph::UNKNOWN_POLY;
|
||||
m_target_node = BattleGraph::UNKNOWN_POLY;
|
||||
m_target_point = Vec3(0,0,0);
|
||||
m_target_angle = 0.0f;
|
||||
m_time_since_stuck = 0.0f;
|
||||
m_currently_reversing = false;
|
||||
m_closest_kart_distance = 99999.9f;
|
||||
AIBaseController::reset();
|
||||
}
|
||||
|
||||
@ -118,107 +122,164 @@ void BattleAI::reset()
|
||||
*/
|
||||
void BattleAI::update(float dt)
|
||||
{
|
||||
|
||||
if (m_world->isStartPhase())
|
||||
{
|
||||
AIBaseController::update(dt);
|
||||
return;
|
||||
}
|
||||
|
||||
handleAcceleration(dt);
|
||||
handleSteering(dt);
|
||||
handleItems(dt);
|
||||
handleBraking();
|
||||
handleGetUnstuck(dt);
|
||||
AIBaseController::update(dt);
|
||||
|
||||
} //update
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Handles acceleration. It also takes the plunger into account.
|
||||
/** Handles acceleration.
|
||||
* \param dt Time step size.
|
||||
*/
|
||||
void BattleAI::handleAcceleration( const float dt)
|
||||
{
|
||||
//Do not accelerate until we have delayed the start enough
|
||||
/* if( m_start_delay > 0.0f )
|
||||
{
|
||||
m_start_delay -= dt;
|
||||
m_controls->m_accel = 0.0f;
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
if( m_controls->m_brake )
|
||||
if(m_controls->m_brake)
|
||||
{
|
||||
m_controls->m_accel = 0.0f;
|
||||
return;
|
||||
}
|
||||
|
||||
if(m_kart->getBlockedByPlungerTime()>0)
|
||||
{
|
||||
if(m_kart->getSpeed() < m_kart->getCurrentMaxSpeed() / 2)
|
||||
m_controls->m_accel = 0.05f;
|
||||
else
|
||||
m_controls->m_accel = 0.0f;
|
||||
return;
|
||||
}
|
||||
|
||||
m_controls->m_accel = stk_config->m_ai_acceleration;
|
||||
|
||||
} // handleAcceleration
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** This function sets the steering.
|
||||
* NOTE: The Battle AI is in development and currently this function is a
|
||||
* sandbox for testing out the AI. It may actually be doing a lot more than
|
||||
* just steering to a point, which means this function could be messy.
|
||||
* \param dt Time step size.
|
||||
*/
|
||||
void BattleAI::handleSteering(const float dt)
|
||||
{
|
||||
const AbstractKart* kart = m_world->getPlayerKart(0);
|
||||
PlayerController* pcontroller = (PlayerController*)kart->getController();
|
||||
if (m_current_node == BattleGraph::UNKNOWN_POLY) return;
|
||||
|
||||
int player_node = pcontroller->getCurrentNode();
|
||||
std::cout<<"PLayer node " << player_node<<" This cpu kart node" << m_current_node<<std::endl;
|
||||
|
||||
if(player_node == BattleGraph::UNKNOWN_POLY || m_current_node == BattleGraph::UNKNOWN_POLY) return;
|
||||
m_target_node = player_node;
|
||||
m_target_point = kart->getXYZ();
|
||||
|
||||
//handleItemCollection(&m_target_point, &m_target_node);
|
||||
m_debug_sphere->setPosition(m_target_point.toIrrVector());
|
||||
if(m_target_node == m_current_node)
|
||||
if (m_kart->getPowerup()->getType()==PowerupManager::POWERUP_NOTHING)
|
||||
{
|
||||
m_target_point=kart->getXYZ();
|
||||
// std::cout<<"Aiming at sire nixt\n";
|
||||
}
|
||||
else
|
||||
handleItemCollection(&m_target_point , &m_target_node);
|
||||
if (m_target_node == BattleGraph::UNKNOWN_POLY) return;
|
||||
|
||||
if (m_target_node != m_current_node)
|
||||
{
|
||||
m_next_node = BattleGraph::get()->getNextShortestPathPoly(m_current_node, m_target_node);
|
||||
|
||||
// std::cout<<"Aiming at "<<next_node<<"\n";
|
||||
if(m_next_node == -1) return;
|
||||
//target_point = NavMesh::get()->getCenterOfPoly(m_next_node);
|
||||
|
||||
findPortals(m_current_node, m_target_node);
|
||||
stringPull(m_kart->getXYZ(),m_target_point);
|
||||
if(m_path_corners.size()>0)
|
||||
stringPull(m_kart->getXYZ(), m_target_point);
|
||||
if (m_path_corners.size() > 0)
|
||||
{
|
||||
m_debug_sphere->setPosition(m_path_corners[0].toIrrVector());
|
||||
//m_debug_sphere->setPosition(m_path_corners[0].toIrrVector());
|
||||
m_target_point = m_path_corners.front();
|
||||
float target_angle = steerToPoint(m_target_point);
|
||||
setSteering(target_angle,dt);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
else if (m_target_node == m_current_node)
|
||||
{
|
||||
// Very close to the item, steer directly
|
||||
float target_angle = steerToPoint(m_target_point);
|
||||
setSteering(target_angle,dt);
|
||||
m_controls->m_brake = true;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
std::cout<<" ZERO CORNERS \n";
|
||||
// Do nothing if no targets found
|
||||
m_target_node = 0;
|
||||
m_target_point = 0.0f;
|
||||
setSteering(0.0f,dt);
|
||||
return;
|
||||
}
|
||||
// target_point = m_path_corners[0];
|
||||
}
|
||||
|
||||
m_target_angle = steerToPoint(m_target_point);
|
||||
// std::cout<<"Target nalge: "<<m_target_angle << " normalized:"<<normalizeAngle(m_target_angle)<<std::endl;
|
||||
setSteering(m_target_angle,dt);
|
||||
//After this AI kart has a powerup, try to follow a closet kart in the map
|
||||
findClosestKart(&m_target_point , &m_target_node);
|
||||
if (m_target_node == BattleGraph::UNKNOWN_POLY) return;
|
||||
|
||||
#ifdef AI_DEBUG
|
||||
// m_debug_sphere->setPosition(target_point.toIrrVector());
|
||||
Log::debug("skidding_ai","-Outside of road: steer to center point.\n");
|
||||
#endif
|
||||
if (m_target_node != m_current_node)
|
||||
{
|
||||
findPortals(m_current_node, m_target_node);
|
||||
stringPull(m_kart->getXYZ(), m_target_point);
|
||||
if (m_path_corners.size() > 0)
|
||||
{
|
||||
//m_debug_sphere->setPosition(m_path_corners[0].toIrrVector());
|
||||
m_target_point = m_path_corners.front();
|
||||
float target_angle = steerToPoint(m_target_point);
|
||||
setSteering(target_angle,dt);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
else if (m_target_node == m_current_node)
|
||||
{
|
||||
// Very close to the target kart, steer directly
|
||||
float target_angle = steerToPoint(m_target_point);
|
||||
setSteering(target_angle,dt);
|
||||
m_controls->m_brake = true;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
// Do nothing if no targets found
|
||||
m_target_node = 0;
|
||||
m_target_point = 0.0f;
|
||||
setSteering(0.0f,dt);
|
||||
}
|
||||
} // handleSteering
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void BattleAI::findClosestKart(Vec3* aim_point, int* target_node)
|
||||
{
|
||||
float distance = 99999.9f;
|
||||
const unsigned int n = m_world->getNumKarts();
|
||||
int closet_kart_num = 0;
|
||||
|
||||
for (unsigned int i = 0; i < n; i++)
|
||||
{
|
||||
const AbstractKart* kart = m_world->getKart(i);
|
||||
if(kart->isEliminated()) continue;
|
||||
|
||||
if (kart->getXYZ() == m_kart->getXYZ())
|
||||
continue; // Skip the same kart
|
||||
|
||||
Vec3 d = kart->getXYZ() - m_kart->getXYZ();
|
||||
if (d.length_2d() <= distance)
|
||||
{
|
||||
distance = d.length_2d();
|
||||
closet_kart_num = i;
|
||||
}
|
||||
}
|
||||
|
||||
const AbstractKart* closet_kart = m_world->getKart(closet_kart_num);
|
||||
if (!closet_kart->getController()->isPlayerController())
|
||||
{
|
||||
BattleAI* controller = (BattleAI*)(closet_kart->getController());
|
||||
*target_node = controller->getCurrentNode();
|
||||
*aim_point = closet_kart->getXYZ();
|
||||
}
|
||||
|
||||
else if (closet_kart->getController()->isPlayerController())
|
||||
{
|
||||
PlayerController* controller = (PlayerController*)(closet_kart->getController());
|
||||
*target_node = controller->getCurrentNode();
|
||||
*aim_point = closet_kart->getXYZ();
|
||||
}
|
||||
m_closest_kart_distance = distance;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** This function finds the polyon edges(portals) that the AI will cross before
|
||||
* reaching its destination. We start from the current polygon and call
|
||||
@ -247,9 +308,10 @@ void BattleAI::findPortals(int start, int end)
|
||||
|
||||
m_portals.clear();
|
||||
|
||||
while(next_node != end && this_node != -1 && next_node != -1 && this_node != end)
|
||||
while (next_node != end && this_node != -1 && next_node != -1 && this_node != end)
|
||||
{
|
||||
next_node = BattleGraph::get()->getNextShortestPathPoly(this_node, end);
|
||||
if (next_node == BattleGraph::UNKNOWN_POLY || next_node == -999) return;
|
||||
|
||||
std::vector<int> this_node_verts =
|
||||
NavMesh::get()->getNavPoly(this_node).getVerticesIndex();
|
||||
@ -262,12 +324,12 @@ void BattleAI::findPortals(int start, int end)
|
||||
|
||||
Vec3 portalLeft, portalRight;
|
||||
//bool flag = 0;
|
||||
for(unsigned int n_i=0; n_i<next_node_verts.size(); n_i++)
|
||||
for (unsigned int n_i = 0; n_i < next_node_verts.size(); n_i++)
|
||||
{
|
||||
for(unsigned int t_i=0; t_i< this_node_verts.size(); t_i++)
|
||||
for (unsigned int t_i = 0; t_i < this_node_verts.size(); t_i++)
|
||||
{
|
||||
if((next_node_verts[n_i] == this_node_verts[t_i])&&
|
||||
(next_node_verts[(n_i+1)%next_node_verts.size()]==
|
||||
if ((next_node_verts[n_i] == this_node_verts[t_i]) &&
|
||||
(next_node_verts[(n_i+1)%next_node_verts.size()] ==
|
||||
this_node_verts[(t_i+1)%this_node_verts.size()]))
|
||||
{
|
||||
portalLeft = NavMesh::get()->
|
||||
@ -277,10 +339,10 @@ void BattleAI::findPortals(int start, int end)
|
||||
}
|
||||
}
|
||||
}
|
||||
m_portals.push_back(std::make_pair(portalLeft,portalRight));
|
||||
m_portals.push_back(std::make_pair(portalLeft, portalRight));
|
||||
// for debugging:
|
||||
//m_debug_sphere->setPosition((portalLeft).toIrrVector());
|
||||
this_node=next_node;
|
||||
this_node = next_node;
|
||||
}
|
||||
} // findPortals
|
||||
|
||||
@ -310,25 +372,23 @@ void BattleAI::stringPull(const Vec3& start_pos, const Vec3& end_pos)
|
||||
Vec3 funnel_left = m_portals[0].first;
|
||||
Vec3 funnel_right = m_portals[0].second;
|
||||
unsigned int apex_index=0, fun_left_index=0, fun_right_index=0;
|
||||
m_portals.push_back(std::make_pair(end_pos,end_pos));
|
||||
m_portals.push_back(std::make_pair(end_pos, end_pos));
|
||||
m_path_corners.clear();
|
||||
const float eps=0.0001f;
|
||||
|
||||
for(unsigned int i=0; i<m_portals.size(); i++)
|
||||
for (unsigned int i = 0; i < m_portals.size(); i++)
|
||||
{
|
||||
Vec3 portal_left = m_portals[i].first;
|
||||
Vec3 portal_right = m_portals[i].second;
|
||||
|
||||
|
||||
//Compute for left edge
|
||||
if((funnel_left==funnel_apex) || portal_left.sideOfLine2D(funnel_apex,funnel_left)<=-eps)
|
||||
if ((funnel_left == funnel_apex) || portal_left.sideOfLine2D(funnel_apex, funnel_left) <= -eps)
|
||||
{
|
||||
funnel_left = 0.98f*portal_left + 0.02f*portal_right;
|
||||
//funnel_left = portal_left;
|
||||
fun_left_index = i;
|
||||
|
||||
|
||||
if( portal_left.sideOfLine2D(funnel_apex,funnel_right)<-eps)
|
||||
if (portal_left.sideOfLine2D(funnel_apex, funnel_right) < -eps)
|
||||
{
|
||||
funnel_apex = funnel_right;
|
||||
apex_index = fun_right_index;
|
||||
@ -342,22 +402,21 @@ void BattleAI::stringPull(const Vec3& start_pos, const Vec3& end_pos)
|
||||
}
|
||||
|
||||
//Compute for right edge
|
||||
if( (funnel_right==funnel_apex) ||portal_right.sideOfLine2D(funnel_apex,funnel_right)>=eps)
|
||||
if ((funnel_right == funnel_apex) || portal_right.sideOfLine2D(funnel_apex, funnel_right) >= eps)
|
||||
{
|
||||
|
||||
funnel_right = 0.98f*portal_right + 0.02f*portal_left;
|
||||
//funnel_right = portal_right;
|
||||
fun_right_index = i;
|
||||
if( portal_right.sideOfLine2D(funnel_apex,funnel_left)>eps)
|
||||
{
|
||||
|
||||
if (portal_right.sideOfLine2D(funnel_apex, funnel_left) > eps)
|
||||
{
|
||||
funnel_apex = funnel_left;
|
||||
apex_index = fun_left_index;
|
||||
m_path_corners.push_back(funnel_apex);
|
||||
|
||||
funnel_left = funnel_apex;
|
||||
funnel_right = funnel_apex;
|
||||
i=apex_index;
|
||||
i = apex_index;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -375,26 +434,18 @@ void BattleAI::stringPull(const Vec3& start_pos, const Vec3& end_pos)
|
||||
*/
|
||||
void BattleAI::handleGetUnstuck(const float dt)
|
||||
{
|
||||
if(isStuck() == true)
|
||||
if (isStuck() == true)
|
||||
{
|
||||
m_time_since_stuck = 0.0f;
|
||||
m_currently_reversing = true;
|
||||
m_controls->reset();
|
||||
}
|
||||
if(m_currently_reversing == true)
|
||||
if (m_currently_reversing == true)
|
||||
{
|
||||
setSteering(-1.0f*m_target_angle,dt);
|
||||
setSteering(-2.0f*m_target_angle,dt);
|
||||
setSteering(-2.0f*m_target_angle,dt);
|
||||
m_controls->m_accel = -0.35f;
|
||||
/*
|
||||
if(m_target_angle > 0)
|
||||
setSteering(M_PI,dt);
|
||||
else setSteering(-M_PI,dt);
|
||||
*/
|
||||
setSteering(-M_PI,dt);
|
||||
m_time_since_stuck += dt;
|
||||
|
||||
|
||||
if(m_time_since_stuck >= 0.6f)
|
||||
{
|
||||
m_currently_reversing = false;
|
||||
@ -403,7 +454,6 @@ void BattleAI::handleGetUnstuck(const float dt)
|
||||
}
|
||||
} // handleGetUnstuck
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** This function handles braking. It calls determineTurnRadius() to find out
|
||||
* the curve radius. Depending on the turn radius, it finds out the maximum
|
||||
@ -414,7 +464,6 @@ void BattleAI::handleBraking()
|
||||
{
|
||||
m_controls->m_brake = false;
|
||||
|
||||
|
||||
// A kart will not brake when the speed is already slower than this
|
||||
// value. This prevents a kart from going too slow (or even backwards)
|
||||
// in tight curves.
|
||||
@ -422,12 +471,12 @@ void BattleAI::handleBraking()
|
||||
|
||||
std::vector<Vec3> points;
|
||||
|
||||
if(m_current_node == -1 || m_next_node == -1 || m_target_node == -1)
|
||||
if (m_current_node == -1 || m_target_node == -1)
|
||||
return;
|
||||
|
||||
points.push_back(m_kart->getXYZ());
|
||||
points.push_back(m_path_corners[0]);
|
||||
points.push_back((m_path_corners.size()>=2)?m_path_corners[1]:m_path_corners[0]);
|
||||
points.push_back((m_path_corners.size()>=2) ? m_path_corners[1] : m_path_corners[0]);
|
||||
|
||||
float current_curve_radius = BattleAI::determineTurnRadius(points);
|
||||
|
||||
@ -435,28 +484,24 @@ void BattleAI::handleBraking()
|
||||
if (d1.length2_2d() < d2.length2_2d())
|
||||
current_curve_radius = d1.length_2d();
|
||||
|
||||
//std::cout<<"\n Radius: " << current_curve_radius;
|
||||
float max_turn_speed =
|
||||
m_kart->getKartProperties()
|
||||
->getSpeedForTurnRadius(current_curve_radius);
|
||||
|
||||
if(m_kart->getSpeed() > max_turn_speed &&
|
||||
if (m_kart->getSpeed() > max_turn_speed &&
|
||||
m_kart->getSpeed()>MIN_SPEED )// &&
|
||||
//fabsf(m_controls->m_steer) > 0.95f )
|
||||
//fabsf(m_controls->m_steer) > 0.95f)
|
||||
{
|
||||
m_controls->m_brake = true;
|
||||
std::cout<<"Braking"<<std::endl;
|
||||
#ifdef DEBUG
|
||||
if(m_ai_debug)
|
||||
Log::debug("SkiddingAI",
|
||||
Log::debug("BattleAI",
|
||||
"speed %f too tight curve: radius %f ",
|
||||
m_kart->getSpeed(),
|
||||
m_kart->getIdent().c_str(),
|
||||
current_curve_radius);
|
||||
#endif
|
||||
}
|
||||
return;
|
||||
|
||||
} // handleBraking
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -470,56 +515,52 @@ void BattleAI::handleBraking()
|
||||
float BattleAI::determineTurnRadius( std::vector<Vec3>& points )
|
||||
{
|
||||
// Declaring variables
|
||||
float a,b,c;
|
||||
float a,b;
|
||||
irr::core::CMatrix4<float> A;
|
||||
irr::core::CMatrix4<float> X;
|
||||
irr::core::CMatrix4<float> B;
|
||||
|
||||
//Populating matrices
|
||||
for(unsigned int i=0; i<3; i++)
|
||||
for (unsigned int i = 0; i < 3; i++)
|
||||
{
|
||||
A(i,0)= points[i].x()*points[i].x();
|
||||
A(i,1)= points[i].x();
|
||||
// std::cout<<"X"<<points[i].x();
|
||||
A(i,2)= 1.0f;
|
||||
A(i,3)= 0.0f;
|
||||
A(i,0) = points[i].x()*points[i].x();
|
||||
A(i,1) = points[i].x();
|
||||
A(i,2) = 1.0f;
|
||||
A(i,3) = 0.0f;
|
||||
}
|
||||
A(3,0)=A(3,1)=A(3,2) = 0.0f;
|
||||
A(3,0) = A(3,1) = A(3,2) = 0.0f;
|
||||
A(3,3) = 1.0f;
|
||||
|
||||
for(unsigned int i=0; i<3; i++)
|
||||
for (unsigned int i = 0; i < 3; i++)
|
||||
{
|
||||
B(i,0)= points[i].z();
|
||||
//std::cout<<"Z"<<points[i].z()<<"\n";
|
||||
B(i,1)= 0.0f;
|
||||
B(i,2)= 0.0f;
|
||||
B(i,3)= 0.0f;
|
||||
B(i,0) = points[i].z();
|
||||
B(i,1) = 0.0f;
|
||||
B(i,2) = 0.0f;
|
||||
B(i,3) = 0.0f;
|
||||
}
|
||||
B(3,0)=B(3,1)=B(3,2)=B(3,3) = 0.0f;
|
||||
B(3,0) = B(3,1) = B(3,2) = B(3,3) = 0.0f;
|
||||
|
||||
//Computing inverse : X = inv(A)*B
|
||||
irr::core::CMatrix4<float> invA;
|
||||
if(!A.getInverse(invA))
|
||||
{
|
||||
if (!A.getInverse(invA))
|
||||
return -1;
|
||||
}
|
||||
|
||||
X = invA*B;
|
||||
a = X(0,0);
|
||||
b = X(0,1);
|
||||
c = X(0,2);
|
||||
//c = X(0,2);
|
||||
|
||||
float x = points.front().x();
|
||||
float z = a*pow(x,2) + b*x + c;
|
||||
//float z = a*pow(x,2) + b*x + c;
|
||||
float dx_by_dz = 2*a*x + b;
|
||||
float d2x_by_dz = 2*a;
|
||||
|
||||
float radius = pow(abs(1 + pow(dx_by_dz,2)),1.5f)/ abs(d2x_by_dz);
|
||||
|
||||
return radius;
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Alternative implementation of isStuck()
|
||||
/*
|
||||
float BattleAI::isStuck(const float dt)
|
||||
@ -544,23 +585,154 @@ float BattleAI::isStuck(const float dt)
|
||||
|
||||
*/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void BattleAI::handleItems(const float dt)
|
||||
{
|
||||
m_controls->m_fire = false;
|
||||
if (m_kart->getPowerup()->getType() == PowerupManager::POWERUP_NOTHING)
|
||||
return;
|
||||
|
||||
m_time_since_last_shot += dt;
|
||||
|
||||
float min_bubble_time = 2.0f;
|
||||
|
||||
switch(m_kart->getPowerup()->getType())
|
||||
{
|
||||
case PowerupManager::POWERUP_BUBBLEGUM:
|
||||
{
|
||||
Attachment::AttachmentType type = m_kart->getAttachment()->getType();
|
||||
// Don't use shield when we have a swatter.
|
||||
if (type == Attachment::ATTACH_SWATTER ||
|
||||
type == Attachment::ATTACH_NOLOKS_SWATTER)
|
||||
break;
|
||||
|
||||
// Check if a flyable (cake, ...) is close. If so, use bubblegum
|
||||
// as shield
|
||||
if (!m_kart->isShielded() &&
|
||||
projectile_manager->projectileIsClose(m_kart,
|
||||
m_ai_properties->m_shield_incoming_radius))
|
||||
{
|
||||
m_controls->m_fire = true;
|
||||
m_controls->m_look_back = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// Avoid dropping all bubble gums one after another
|
||||
if (m_time_since_last_shot < 3.0f) break;
|
||||
|
||||
// Use bubblegum if the next kart behind is 'close' but not too close
|
||||
// (too close likely means that the kart is not behind but more to the
|
||||
// side of this kart and so won't be hit by the bubble gum anyway).
|
||||
// Should we check the speed of the kart as well? I.e. only drop if
|
||||
// the kart behind is faster? Otoh this approach helps preventing an
|
||||
// overtaken kart to overtake us again.
|
||||
if (m_closest_kart_distance < 15.0f && m_closest_kart_distance > 3.0f)
|
||||
{
|
||||
m_controls->m_fire = true;
|
||||
m_controls->m_look_back = true;
|
||||
break;
|
||||
}
|
||||
|
||||
break; // POWERUP_BUBBLEGUM
|
||||
}
|
||||
// All the thrown/fired items might be improved by considering the angle
|
||||
// towards m_kart_ahead.
|
||||
case PowerupManager::POWERUP_CAKE:
|
||||
{
|
||||
// if the kart has a shield, do not break it by using a cake.
|
||||
if (m_kart->getShieldTime() > min_bubble_time)
|
||||
break;
|
||||
// Leave some time between shots
|
||||
if (m_time_since_last_shot < 3.0f) break;
|
||||
|
||||
if (m_closest_kart_distance < 25.0f)
|
||||
{
|
||||
m_controls->m_fire = true;
|
||||
m_controls->m_look_back = false;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
} // POWERUP_CAKE
|
||||
|
||||
case PowerupManager::POWERUP_BOWLING:
|
||||
{
|
||||
// if the kart has a shield, do not break it by using a bowling ball.
|
||||
if (m_kart->getShieldTime() > min_bubble_time)
|
||||
break;
|
||||
// Leave more time between bowling balls, since they are
|
||||
// slower, so it should take longer to hit something which
|
||||
// can result in changing our target.
|
||||
if (m_time_since_last_shot < 5.0f) break;
|
||||
|
||||
if (m_closest_kart_distance < 5.0f)
|
||||
{
|
||||
m_controls->m_fire = true;
|
||||
m_controls->m_look_back = false;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
} // POWERUP_BOWLING
|
||||
|
||||
case PowerupManager::POWERUP_SWATTER:
|
||||
{
|
||||
// if the kart has a shield, do not break it by using a swatter.
|
||||
if(m_kart->getShieldTime() > min_bubble_time)
|
||||
break;
|
||||
|
||||
if (m_closest_kart_distance < 5.0f)
|
||||
{
|
||||
m_controls->m_fire = true;
|
||||
m_controls->m_look_back = false;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Below powerups won't appear in battle mode, so skip them
|
||||
case PowerupManager::POWERUP_ZIPPER:
|
||||
break; // POWERUP_ZIPPER
|
||||
|
||||
case PowerupManager::POWERUP_PLUNGER:
|
||||
break; // POWERUP_PLUNGER
|
||||
|
||||
case PowerupManager::POWERUP_SWITCH: // Don't handle switch
|
||||
m_controls->m_fire = true; // (use it no matter what) for now
|
||||
break; // POWERUP_SWITCH
|
||||
|
||||
case PowerupManager::POWERUP_PARACHUTE:
|
||||
break; // POWERUP_PARACHUTE
|
||||
|
||||
case PowerupManager::POWERUP_ANVIL:
|
||||
break; // POWERUP_ANVIL
|
||||
|
||||
case PowerupManager::POWERUP_RUBBERBALL:
|
||||
break;
|
||||
|
||||
default:
|
||||
Log::error("BattleAI",
|
||||
"Invalid or unhandled powerup '%d' in default AI.",
|
||||
m_kart->getPowerup()->getType());
|
||||
assert(false);
|
||||
}
|
||||
if (m_controls->m_fire)
|
||||
{
|
||||
m_closest_kart_distance = 99999.9f;
|
||||
m_time_since_last_shot = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void BattleAI::handleItemCollection(Vec3 *aim_point, int* target_node)
|
||||
void BattleAI::handleItemCollection(Vec3* aim_point, int* target_node)
|
||||
{
|
||||
if (m_kart->getPowerup()->getType() == PowerupManager::POWERUP_BOWLING) return;
|
||||
Vec3 old_aim_point = *aim_point;
|
||||
|
||||
float distance = 5.0f;
|
||||
bool found_suitable_item = false;
|
||||
const std::vector< std::pair<Item*, int> >& item_list =
|
||||
BattleGraph::get()->getItemList();
|
||||
int items_count = item_list.size();
|
||||
|
||||
unsigned int items_count = item_list.size();
|
||||
|
||||
for (unsigned int j = 0; j < 50; j++)
|
||||
{
|
||||
@ -570,7 +742,8 @@ void BattleAI::handleItemCollection(Vec3 *aim_point, int* target_node)
|
||||
Vec3 d = item->getXYZ() - m_kart->getXYZ();
|
||||
if (d.length_2d() <= distance)
|
||||
{
|
||||
if (item->getType() == Item::ITEM_BONUS_BOX && !item->wasCollected())
|
||||
if ((item->getType() == Item::ITEM_BONUS_BOX)
|
||||
&& !item->wasCollected())
|
||||
{
|
||||
m_item_to_collect = item;
|
||||
found_suitable_item = true;
|
||||
@ -580,8 +753,7 @@ void BattleAI::handleItemCollection(Vec3 *aim_point, int* target_node)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (found_suitable_item) break;
|
||||
distance = 2.0f * distance;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -20,7 +20,7 @@
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifndef HEADER_BATTLE_AI_HPP
|
||||
#define HEADER_BATTLE_AI__HPP
|
||||
#define HEADER_BATTLE_AI_HPP
|
||||
|
||||
#include "karts/controller/ai_base_controller.hpp"
|
||||
#include "race/race_manager.hpp"
|
||||
@ -50,18 +50,12 @@ private:
|
||||
* updated in ThreeStrikesBattle::updateKartNodes() */
|
||||
int m_current_node;
|
||||
|
||||
/** Holds the next node the kart is expected to drive to. Currently unused. */
|
||||
int m_next_node;
|
||||
|
||||
/** The node(poly) at which the target point lies in. */
|
||||
int m_target_node;
|
||||
|
||||
/** The target point. */
|
||||
Vec3 m_target_point;
|
||||
|
||||
/** The steering angle required to reach the target point. */
|
||||
float m_target_angle;
|
||||
|
||||
/** Holds the set of portals that the kart will cross when moving through
|
||||
* polygon channel. See findPortals() */
|
||||
std::vector<std::pair<Vec3,Vec3> > m_portals;
|
||||
@ -70,6 +64,9 @@ private:
|
||||
* will eventaully move through. See stringPull() */
|
||||
std::vector<Vec3> m_path_corners;
|
||||
|
||||
/** Time an item has been collected and not used. */
|
||||
float m_time_since_last_shot;
|
||||
|
||||
/** This is a timer that counts down when the kart is reversing to get unstuck */
|
||||
float m_time_since_stuck;
|
||||
|
||||
@ -77,17 +74,21 @@ private:
|
||||
* counting down. */
|
||||
bool m_currently_reversing;
|
||||
|
||||
float m_closest_kart_distance;
|
||||
|
||||
const Item *m_item_to_collect;
|
||||
|
||||
float determineTurnRadius(std::vector<Vec3>& points);
|
||||
void findPortals(int start, int end);
|
||||
void stringPull(const Vec3&, const Vec3&);
|
||||
void handleAcceleration(const float dt) ;
|
||||
void handleAcceleration(const float dt);
|
||||
void handleSteering(const float dt);
|
||||
void handleBraking();
|
||||
void handleGetUnstuck(const float dt);
|
||||
void handleItems(const float dt);
|
||||
|
||||
void handleItemCollection(Vec3*, int*);
|
||||
void findClosestKart(Vec3*, int*);
|
||||
|
||||
protected:
|
||||
|
||||
@ -119,7 +120,7 @@ public:
|
||||
virtual bool isPlayerController() const { return false; }
|
||||
virtual void action(PlayerAction action, int value) {};
|
||||
virtual void skidBonusTriggered() {};
|
||||
virtual bool disableSlipstreamBonus() const {return 0;}
|
||||
virtual bool disableSlipstreamBonus() const {return 0; }
|
||||
virtual void newLap(int lap) {};
|
||||
};
|
||||
|
||||
|
@ -60,7 +60,7 @@
|
||||
#include <iostream>
|
||||
|
||||
SkiddingAI::SkiddingAI(AbstractKart *kart)
|
||||
: AIBaseController(kart)
|
||||
: AIBaseLapController(kart)
|
||||
{
|
||||
reset();
|
||||
// Determine if this AI has superpowers, which happens e.g.
|
||||
@ -179,7 +179,7 @@ void SkiddingAI::reset()
|
||||
m_skid_probability_state = SKID_PROBAB_NOT_YET;
|
||||
m_last_item_random = NULL;
|
||||
|
||||
AIBaseController::reset();
|
||||
AIBaseLapController::reset();
|
||||
m_track_node = QuadGraph::UNKNOWN_SECTOR;
|
||||
QuadGraph::get()->findRoadSector(m_kart->getXYZ(), &m_track_node);
|
||||
if(m_track_node==QuadGraph::UNKNOWN_SECTOR)
|
||||
@ -191,7 +191,7 @@ void SkiddingAI::reset()
|
||||
m_track_node = QuadGraph::get()->findOutOfRoadSector(m_kart->getXYZ());
|
||||
}
|
||||
|
||||
AIBaseController::reset();
|
||||
AIBaseLapController::reset();
|
||||
} // reset
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -296,14 +296,14 @@ void SkiddingAI::update(float dt)
|
||||
if(isStuck() && !m_kart->getKartAnimation())
|
||||
{
|
||||
new RescueAnimation(m_kart);
|
||||
AIBaseController::update(dt);
|
||||
AIBaseLapController::update(dt);
|
||||
return;
|
||||
}
|
||||
|
||||
if( m_world->isStartPhase() )
|
||||
{
|
||||
handleRaceStart();
|
||||
AIBaseController::update(dt);
|
||||
AIBaseLapController::update(dt);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -378,7 +378,7 @@ void SkiddingAI::update(float dt)
|
||||
}
|
||||
|
||||
/*And obviously general kart stuff*/
|
||||
AIBaseController::update(dt);
|
||||
AIBaseLapController::update(dt);
|
||||
} // update
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -2194,7 +2194,7 @@ void SkiddingAI::handleCurve()
|
||||
/** Determines if the kart should skid. The base implementation enables
|
||||
* skidding
|
||||
* \param steer_fraction The steering fraction as computed by the
|
||||
* AIBaseController.
|
||||
* AIBaseLapController.
|
||||
* \return True if the kart should skid.
|
||||
*/
|
||||
bool SkiddingAI::doSkid(float steer_fraction)
|
||||
|
@ -57,14 +57,6 @@ void ThreeStrikesBattle::init()
|
||||
{
|
||||
WorldWithRank::init();
|
||||
m_display_rank = false;
|
||||
|
||||
// check for possible problems if AI karts were incorrectly added
|
||||
// FIXME : remove this bit of code in future since ai will be added
|
||||
/* if(getNumKarts() > race_manager->getNumPlayers())
|
||||
{
|
||||
Log::fatal("[Three Strikes Battle]", "No AI exists for this game mode");
|
||||
}
|
||||
*/
|
||||
m_kart_info.resize(m_karts.size());
|
||||
} // ThreeStrikesBattle
|
||||
|
||||
@ -300,8 +292,8 @@ void ThreeStrikesBattle::update(float dt)
|
||||
WorldWithRank::update(dt);
|
||||
WorldWithRank::updateTrack(dt);
|
||||
|
||||
PhysicalObject::BodyTypes body_shape;
|
||||
updateKartNodes(); // insert blown away tire(s) now if was requested
|
||||
|
||||
while (m_insert_tire > 0)
|
||||
{
|
||||
std::string tire;
|
||||
@ -453,7 +445,7 @@ void ThreeStrikesBattle::updateKartNodes()
|
||||
|
||||
int saved_current_node = controller->getCurrentNode();
|
||||
|
||||
if(controller->getCurrentNode()!= BattleGraph::UNKNOWN_POLY)
|
||||
if (saved_current_node != BattleGraph::UNKNOWN_POLY)
|
||||
{
|
||||
//check if the kart is still on the same node
|
||||
const NavPoly& p = BattleGraph::get()->getPolyOfNode(controller->getCurrentNode());
|
||||
@ -468,7 +460,6 @@ void ThreeStrikesBattle::updateKartNodes()
|
||||
// useful in cases when you are "teleported" to some other poly, ex. rescue
|
||||
controller->setCurrentNode(BattleGraph::UNKNOWN_POLY);
|
||||
|
||||
|
||||
for(unsigned int i=0; i<adjacents.size(); i++)
|
||||
{
|
||||
const NavPoly& p_temp =
|
||||
@ -476,23 +467,20 @@ void ThreeStrikesBattle::updateKartNodes()
|
||||
if(p_temp.pointInPoly(kart->getXYZ()))
|
||||
controller->setCurrentNode(adjacents[i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//Current node is still unkown
|
||||
if(controller->getCurrentNode() == BattleGraph::UNKNOWN_POLY)
|
||||
if (saved_current_node == BattleGraph::UNKNOWN_POLY)
|
||||
{
|
||||
bool flag = 0;
|
||||
unsigned int max_count = BattleGraph::get()->getNumNodes();
|
||||
//float min_dist = 9999.99f;
|
||||
for(unsigned int i =0; i<max_count; i++)
|
||||
for(unsigned int i=0; i<max_count; i++)
|
||||
{
|
||||
const NavPoly& p = BattleGraph::get()->getPolyOfNode(i);
|
||||
if((p.pointInPoly(kart->getXYZ())))
|
||||
{
|
||||
controller->setCurrentNode(i);
|
||||
flag = 1;
|
||||
//min_dist = (p.getCenter() - m_kart->getXYZ()).length_2d();
|
||||
}
|
||||
}
|
||||
|
||||
@ -506,7 +494,7 @@ void ThreeStrikesBattle::updateKartNodes()
|
||||
|
||||
int saved_current_node = controller->getCurrentNode();
|
||||
|
||||
if(controller->getCurrentNode()!= BattleGraph::UNKNOWN_POLY)
|
||||
if (saved_current_node != BattleGraph::UNKNOWN_POLY)
|
||||
{
|
||||
//check if the kart is still on the same node
|
||||
const NavPoly& p = BattleGraph::get()->getPolyOfNode(controller->getCurrentNode());
|
||||
@ -521,7 +509,6 @@ void ThreeStrikesBattle::updateKartNodes()
|
||||
// useful in cases when you are "teleported" to some other poly, ex. rescue
|
||||
controller->setCurrentNode(BattleGraph::UNKNOWN_POLY);
|
||||
|
||||
|
||||
for(unsigned int i=0; i<adjacents.size(); i++)
|
||||
{
|
||||
const NavPoly& p_temp =
|
||||
@ -529,14 +516,12 @@ void ThreeStrikesBattle::updateKartNodes()
|
||||
if(p_temp.pointInPoly(kart->getXYZ()))
|
||||
controller->setCurrentNode(adjacents[i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(controller->getCurrentNode() == BattleGraph::UNKNOWN_POLY)
|
||||
if (saved_current_node == BattleGraph::UNKNOWN_POLY)
|
||||
{
|
||||
bool flag = 0;
|
||||
unsigned int max_count = BattleGraph::get()->getNumNodes();
|
||||
//float min_dist = 9999.99f;
|
||||
for(unsigned int i =0; i<max_count; i++)
|
||||
{
|
||||
const NavPoly& p = BattleGraph::get()->getPolyOfNode(i);
|
||||
@ -544,7 +529,6 @@ void ThreeStrikesBattle::updateKartNodes()
|
||||
{
|
||||
controller->setCurrentNode(i);
|
||||
flag = 1;
|
||||
//min_dist = (p.getCenter() - m_kart->getXYZ()).length_2d();
|
||||
}
|
||||
}
|
||||
|
||||
@ -554,7 +538,6 @@ void ThreeStrikesBattle::updateKartNodes()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** 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,
|
||||
|
@ -98,7 +98,6 @@ void RaceSetupScreen::eventCallback(Widget* widget, const std::string& name, con
|
||||
{
|
||||
race_manager->setMinorMode(RaceManager::MINOR_MODE_3_STRIKES);
|
||||
UserConfigParams::m_game_mode = CONFIG_CODE_3STRIKES;
|
||||
race_manager->setNumKarts( race_manager->getNumLocalPlayers() ); // no AI karts;
|
||||
ArenasScreen::getInstance()->push();
|
||||
}
|
||||
else if (selectedMode == IDENT_EASTER)
|
||||
@ -223,17 +222,14 @@ void RaceSetupScreen::init()
|
||||
w2->addItem(name3, IDENT_FTL, RaceManager::getIconOf(RaceManager::MINOR_MODE_FOLLOW_LEADER), false);
|
||||
}
|
||||
|
||||
if (race_manager->getNumLocalPlayers() > 1 || UserConfigParams::m_artist_debug_mode)
|
||||
{
|
||||
irr::core::stringw name4 = irr::core::stringw(
|
||||
RaceManager::getNameOf(RaceManager::MINOR_MODE_3_STRIKES)) + L"\n";
|
||||
//FIXME: avoid duplicating descriptions from the help menu!
|
||||
name4 += _("Hit others with weapons until they lose all their lives (only in multiplayer games).");
|
||||
w2->addItem( name4, IDENT_STRIKES, RaceManager::getIconOf(RaceManager::MINOR_MODE_3_STRIKES));
|
||||
}
|
||||
|
||||
#ifdef ENABLE_SOCCER_MODE
|
||||
if (race_manager->getNumLocalPlayers() > 1 || UserConfigParams::m_artist_debug_mode)
|
||||
if (race_manager->getNumLocalPlayers() > 1 || UserConfigParams::m_artist_debug_mode)
|
||||
{
|
||||
irr::core::stringw name5 = irr::core::stringw(
|
||||
RaceManager::getNameOf(RaceManager::MINOR_MODE_SOCCER)) + L"\n";
|
||||
@ -244,6 +240,7 @@ if (race_manager->getNumLocalPlayers() > 1 || UserConfigParams::m_artist_debug_m
|
||||
|
||||
#define ENABLE_EASTER_EGG_MODE
|
||||
#ifdef ENABLE_EASTER_EGG_MODE
|
||||
if(race_manager->getNumLocalPlayers() == 1)
|
||||
{
|
||||
irr::core::stringw name1 = irr::core::stringw(
|
||||
RaceManager::getNameOf(RaceManager::MINOR_MODE_EASTER_EGG)) + L"\n";
|
||||
|
@ -26,10 +26,9 @@
|
||||
#include "graphics/irr_driver.hpp"
|
||||
#include "items/item_manager.hpp"
|
||||
#include "tracks/navmesh.hpp"
|
||||
#include "utils/log.hpp"
|
||||
#include "utils/vec3.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
const int BattleGraph::UNKNOWN_POLY = -1;
|
||||
BattleGraph * BattleGraph::m_battle_graph = NULL;
|
||||
|
||||
@ -81,7 +80,7 @@ void BattleGraph::buildGraph(NavMesh* navmesh)
|
||||
*/
|
||||
void BattleGraph::computeFloydWarshall()
|
||||
{
|
||||
int n = getNumNodes();
|
||||
unsigned int n = getNumNodes();
|
||||
|
||||
// initialize m_parent_poly with unknown_poly so that if no path is found b/w i and j
|
||||
// then m_parent_poly[i][j] = -1 (UNKNOWN_POLY)
|
||||
@ -136,11 +135,10 @@ void BattleGraph::createMesh(bool enable_transparency,
|
||||
m_mesh_buffer = m_mesh->getMeshBuffer(0);
|
||||
assert(m_mesh_buffer->getVertexType()==video::EVT_STANDARD);
|
||||
|
||||
|
||||
// Eps is used to raise the track debug quads a little bit higher than
|
||||
// the ground, so that they are actually visible.
|
||||
core::vector3df eps(0, 0.4f, 0);
|
||||
video::SColor defaultColor(255, 255, 0, 0), c;
|
||||
video::SColor c = video::SColor(255, 255, 0, 0);
|
||||
|
||||
// Declare vector to hold new converted vertices, vertices are copied over
|
||||
// for each polygon, although it results in redundant vertex copies in the
|
||||
@ -200,8 +198,6 @@ void BattleGraph::createMesh(bool enable_transparency,
|
||||
ind.push_back(i++);
|
||||
ind.push_back(i++);
|
||||
ind.push_back(i++);
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -223,10 +219,10 @@ void BattleGraph::createDebugMesh()
|
||||
{
|
||||
if(getNumNodes()<=0) return; // no debug output if not graph
|
||||
|
||||
createMesh(/*enable_transparency*/true);
|
||||
m_node = irr_driver->addMesh(m_mesh);
|
||||
createMesh(/*enable_transparency*/false);
|
||||
m_node = irr_driver->addMesh(m_mesh, "track-debug-mesh");
|
||||
#ifdef DEBUG
|
||||
m_node->setName("track-debug-mesh");
|
||||
// m_node->setName("track-debug-mesh");
|
||||
#endif
|
||||
|
||||
} // createDebugMesh
|
||||
@ -245,6 +241,7 @@ void BattleGraph::cleanupDebugMesh()
|
||||
m_mesh = NULL;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void BattleGraph::findItemsOnGraphNodes(ItemManager * item_manager)
|
||||
{
|
||||
@ -255,24 +252,28 @@ void BattleGraph::findItemsOnGraphNodes(ItemManager * item_manager)
|
||||
Item* item = item_manager->getItem(i);
|
||||
Vec3 xyz = item->getXYZ();
|
||||
int polygon = BattleGraph::UNKNOWN_POLY;
|
||||
float min_dist = 999999.9f;
|
||||
|
||||
for (unsigned int j = 0; j < this->getNumNodes(); ++j)
|
||||
{
|
||||
if (NavMesh::get()->getNavPoly(j).pointInPoly(xyz))
|
||||
{
|
||||
float dist = xyz.getY() - NavMesh::get()->getCenterOfPoly(j).getY();
|
||||
if (dist < min_dist && dist>-1.0f)
|
||||
{
|
||||
polygon = j;
|
||||
min_dist = dist;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (polygon != BattleGraph::UNKNOWN_POLY)
|
||||
{
|
||||
m_items_on_graph.push_back(std::make_pair(item, polygon));
|
||||
|
||||
Log::debug("BattleGraph","item number %d is on polygon %d", i, polygon);
|
||||
}
|
||||
else
|
||||
Log::debug("BattleGraph","Can't map item number %d with a suitable polygon", i);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
const int & BattleGraph::getNextShortestPathPoly(int i, int j) const
|
||||
{
|
||||
if (i == BattleGraph::UNKNOWN_POLY || j == BattleGraph::UNKNOWN_POLY)
|
||||
return BattleGraph::UNKNOWN_POLY;
|
||||
return m_parent_poly[j][i];
|
||||
}
|
@ -25,7 +25,6 @@
|
||||
|
||||
#include "tracks/navmesh.hpp"
|
||||
|
||||
|
||||
class Navmesh;
|
||||
class Item;
|
||||
class ItemManager;
|
||||
@ -51,7 +50,6 @@ class BattleGraph
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
static BattleGraph *m_battle_graph;
|
||||
|
||||
/** The actual graph data structure, it is an adjacency matrix */
|
||||
@ -80,7 +78,6 @@ private:
|
||||
~BattleGraph(void);
|
||||
|
||||
public:
|
||||
|
||||
static const int UNKNOWN_POLY;
|
||||
|
||||
/** Returns the one instance of this object. */
|
||||
@ -119,8 +116,7 @@ public:
|
||||
/** Returns the next polygon on the shortest path from i to j.
|
||||
* Note: m_parent_poly[j][i] contains the parent of i on path from j to i,
|
||||
* which is the next node on the path from i to j (undirected graph) */
|
||||
const int & getNextShortestPathPoly(int i, int j) const
|
||||
{ return m_parent_poly[j][i]; }
|
||||
const int & getNextShortestPathPoly(int i, int j) const;
|
||||
|
||||
const std::vector< std::pair<Item*, int> >& getItemList()
|
||||
{ return m_items_on_graph; }
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2009 Joerg Henrichs
|
||||
// Copyright (C) 2009-2015 Joerg Henrichs
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
@ -16,15 +16,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 "tracks/nav_poly.hpp"
|
||||
#include "tracks/navmesh.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
|
||||
/** Constructor that takes a vector of points and a vector of adjacnet polygons */
|
||||
/** Constructor that takes a vector of points and a vector of adjacent polygons */
|
||||
NavPoly::NavPoly(const std::vector<int> &polygonVertIndices,
|
||||
const std::vector<int> &adjacentPolygonIndices)
|
||||
{
|
||||
@ -42,6 +40,7 @@ NavPoly::NavPoly(const std::vector<int> &polygonVertIndices,
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
const std::vector<Vec3> NavPoly::getVertices()
|
||||
{
|
||||
@ -51,6 +50,8 @@ const std::vector<Vec3> NavPoly::getVertices()
|
||||
return points;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool NavPoly::pointInPoly(const Vec3& p) const
|
||||
{
|
||||
std::vector<Vec3> points;
|
||||
@ -60,7 +61,6 @@ bool NavPoly::pointInPoly(const Vec3& p) const
|
||||
// The point is on which side of the first edge
|
||||
float side = p.sideOfLine2D(points[0],points[1]);
|
||||
|
||||
|
||||
// The point is inside the polygon if it is on the same side for all edges
|
||||
for(unsigned int i=1; i<points.size(); i++)
|
||||
{
|
||||
@ -73,10 +73,9 @@ bool NavPoly::pointInPoly(const Vec3& p) const
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
const Vec3& NavPoly::operator[](int i) const
|
||||
{
|
||||
return NavMesh::get()->getVertex(m_vertices[i]);
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,6 @@
|
||||
#ifndef HEADER_NAV_POLY_HPP
|
||||
#define HEADER_NAV_POLY_HPP
|
||||
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <SColor.h>
|
||||
@ -31,7 +30,6 @@
|
||||
class NavPoly
|
||||
{
|
||||
private:
|
||||
|
||||
/** Holds the index of vertices for a polygon **/
|
||||
std::vector<int> m_vertices;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2009 Joerg Henrichs
|
||||
// Copyright (C) 2009-2015 Joerg Henrichs
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
@ -23,7 +23,6 @@
|
||||
#include <S3DVertex.h>
|
||||
#include <triangle3d.h>
|
||||
|
||||
|
||||
#include "LinearMath/btTransform.h"
|
||||
#include "io/file_manager.hpp"
|
||||
#include "io/xml_node.hpp"
|
||||
@ -31,7 +30,6 @@
|
||||
|
||||
NavMesh *NavMesh::m_nav_mesh = NULL;
|
||||
|
||||
|
||||
/** Constructor, loads the mesh information from a given set of polygons
|
||||
* from a navmesh.xml file.
|
||||
* \param filename Name of the file containing all polygons
|
||||
@ -130,4 +128,3 @@ void NavMesh::readVertex(const XMLNode *xml, Vec3* result) const
|
||||
Vec3 temp(x, y, z);
|
||||
*result = temp;
|
||||
} // readVertex
|
||||
|
||||
|
@ -27,14 +27,12 @@
|
||||
|
||||
#include "utils/vec3.hpp"
|
||||
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video { struct S3DVertex; }
|
||||
}
|
||||
using namespace irr;
|
||||
|
||||
|
||||
class btTransform;
|
||||
class XMLNode;
|
||||
|
||||
@ -55,7 +53,6 @@ class NavMesh
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
static NavMesh *m_nav_mesh;
|
||||
|
||||
/** The actual set of nav polys that constitute the nav mesh */
|
||||
@ -77,7 +74,6 @@ private:
|
||||
~NavMesh();
|
||||
|
||||
public:
|
||||
|
||||
/** Creates a NavMesh instance. */
|
||||
static void create(const std::string &filename)
|
||||
{
|
||||
@ -145,6 +141,4 @@ public:
|
||||
{return m_polys[n].getVertices();}
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -708,14 +708,18 @@ void Track::loadQuadGraph(unsigned int mode_id, const bool reverse)
|
||||
}
|
||||
}
|
||||
} // loadQuadGraph
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
/** Loads the polygon graph for battle, i.e. the definition of all polys, and the way
|
||||
* they are connected to each other. Input file name is hardcoded for now
|
||||
*/
|
||||
void Track::loadBattleGraph()
|
||||
{
|
||||
BattleGraph::create(m_root+"navmesh.xml");
|
||||
}// -----------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void Track::mapPoint2MiniMap(const Vec3 &xyz, Vec3 *draw_at) const
|
||||
{
|
||||
QuadGraph::get()->mapPoint2MiniMap(xyz, draw_at);
|
||||
@ -1596,7 +1600,6 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id)
|
||||
// map to.
|
||||
if (!m_is_arena && !m_is_soccer && !m_is_cutscene) loadQuadGraph(mode_id, reverse_track);
|
||||
|
||||
|
||||
ItemManager::create();
|
||||
|
||||
// Set the default start positions. Node that later the default
|
||||
@ -1829,7 +1832,6 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id)
|
||||
// to the main problem.
|
||||
if (m_is_arena && !m_is_soccer && !m_is_cutscene) loadBattleGraph();
|
||||
|
||||
|
||||
if (UserConfigParams::m_track_debug &&
|
||||
race_manager->getMinorMode()!=RaceManager::MINOR_MODE_3_STRIKES &&
|
||||
!m_is_cutscene)
|
||||
@ -1842,7 +1844,6 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id)
|
||||
!m_is_cutscene)
|
||||
BattleGraph::get()->createDebugMesh();
|
||||
|
||||
|
||||
// Only print warning if not in battle mode, since battle tracks don't have
|
||||
// any quads or check lines.
|
||||
if (CheckManager::get()->getCheckStructureCount()==0 &&
|
||||
@ -1876,8 +1877,6 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id)
|
||||
}
|
||||
|
||||
irr_driver->unsetTextureErrorMessage();
|
||||
|
||||
|
||||
} // loadTrackModel
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
Loading…
x
Reference in New Issue
Block a user