Let spare tire karts follow bounding box points

This commit is contained in:
Benau
2016-10-11 10:52:08 +08:00
parent d1c1435b55
commit fb79cf3a6e
6 changed files with 51 additions and 31 deletions

View File

@@ -28,6 +28,8 @@
#include "physics/physics.hpp"
#include "utils/random_generator.hpp"
#include <algorithm>
SpareTireAI::SpareTireAI(AbstractKart *kart)
: BattleAI(kart)
{
@@ -36,6 +38,16 @@ SpareTireAI::SpareTireAI(AbstractKart *kart)
// billboard showing 'AIBaseController' to the kart.
Controller::setControllerName("SpareTireAI");
// Pre-load the 4 nodes of bounding box defined by battle world
memcpy(m_fixed_target_nodes, m_graph->getBBNodes(), 4 * sizeof(int));
// Reverse the order depends on world ID, so not all spare tire karts go
// the same way
if (m_kart->getWorldKartId() % 2 != 0)
{
std::reverse(std::begin(m_fixed_target_nodes),
std::end(m_fixed_target_nodes));
}
} // SpareTireAI
//-----------------------------------------------------------------------------
@@ -44,7 +56,6 @@ SpareTireAI::SpareTireAI(AbstractKart *kart)
void SpareTireAI::reset()
{
BattleAI::reset();
m_fixed_target_nodes.clear();
m_idx = 0;
m_timer = 0.0f;
} // reset
@@ -62,30 +73,11 @@ void SpareTireAI::update(float dt)
//-----------------------------------------------------------------------------
void SpareTireAI::findDefaultPath()
{
// Randomly find 3 nodes for spare tire kart to move
assert(m_fixed_target_nodes.empty());
const int nodes = m_graph->getNumNodes();
const float min_dist = sqrtf(nodes);
// Randomly find a start node for spare tire kart to move
assert(m_idx == -1);
RandomGenerator random;
while (m_fixed_target_nodes.size() < 3)
{
int node = random.get(nodes);
if (m_fixed_target_nodes.empty())
{
m_fixed_target_nodes.push_back(node);
continue;
}
bool succeed = true;
for (const int& all_node : m_fixed_target_nodes)
{
float dist = m_graph->getDistance(all_node, node);
if (dist < min_dist)
succeed = false;
}
if (succeed)
m_fixed_target_nodes.push_back(node);
}
m_idx = 0;
m_idx = random.get(4);
m_target_node = m_fixed_target_nodes[m_idx];
} // findDefaultPath
@@ -93,11 +85,9 @@ void SpareTireAI::findDefaultPath()
//-----------------------------------------------------------------------------
void SpareTireAI::findTarget()
{
if (m_fixed_target_nodes.empty()) return;
assert(m_fixed_target_nodes.size() == 3);
assert(m_idx != -1 && m_idx < 4);
if (getCurrentNode() == m_fixed_target_nodes[m_idx])
m_idx = m_idx == 2 ? 0 : m_idx + 1;
m_idx = m_idx == 3 ? 0 : m_idx + 1;
const int chosen_node = m_fixed_target_nodes[m_idx];
m_target_node = chosen_node;
@@ -120,7 +110,7 @@ void SpareTireAI::spawn(float time_to_last)
//-----------------------------------------------------------------------------
void SpareTireAI::unspawn()
{
reset();
m_idx = -1;
m_kart->eliminate();
} // unspawn

View File

@@ -27,7 +27,7 @@
class SpareTireAI : public BattleAI
{
private:
std::vector<int> m_fixed_target_nodes;
int m_fixed_target_nodes[4];
int m_idx;
@@ -42,7 +42,7 @@ public:
virtual void reset() OVERRIDE;
void spawn(float time_to_last);
void unspawn();
bool isMoving() const { return !m_fixed_target_nodes.empty(); }
bool isMoving() const { return m_idx != -1; }
};
#endif

View File

@@ -44,6 +44,8 @@ ArenaGraph::ArenaGraph(const std::string &navmesh, const XMLNode *node)
if (node && race_manager->getMinorMode() == RaceManager::MINOR_MODE_SOCCER)
loadGoalNodes(node);
loadBoundingBoxNodes();
} // ArenaGraph
// -----------------------------------------------------------------------------

View File

@@ -223,6 +223,8 @@ void DriveGraph::load(const std::string &quad_file_name,
m_lap_length = l;
}
loadBoundingBoxNodes();
} // load
// ----------------------------------------------------------------------------

View File

@@ -46,6 +46,7 @@ Graph::Graph()
m_new_rtt = NULL;
m_bb_min = Vec3( 99999, 99999, 99999);
m_bb_max = Vec3(-99999, -99999, -99999);
memset(m_bb_nodes, 0, 4 * sizeof(int));
} // Graph
// -----------------------------------------------------------------------------
@@ -618,3 +619,16 @@ int Graph::findOutOfRoadSector(const Vec3& xyz, const int curr_sector,
}
return min_sector;
} // findOutOfRoadSector
//-----------------------------------------------------------------------------
void Graph::loadBoundingBoxNodes()
{
m_bb_nodes[0] = findOutOfRoadSector(Vec3(m_bb_min.x(), 0, m_bb_min.z()),
-1/*curr_sector*/, NULL/*all_sectors*/, true/*ignore_vertical*/);
m_bb_nodes[1] = findOutOfRoadSector(Vec3(m_bb_min.x(), 0, m_bb_max.z()),
-1/*curr_sector*/, NULL/*all_sectors*/, true/*ignore_vertical*/);
m_bb_nodes[2] = findOutOfRoadSector(Vec3(m_bb_max.x(), 0, m_bb_min.z()),
-1/*curr_sector*/, NULL/*all_sectors*/, true/*ignore_vertical*/);
m_bb_nodes[3] = findOutOfRoadSector(Vec3(m_bb_max.x(), 0, m_bb_max.z()),
-1/*curr_sector*/, NULL/*all_sectors*/, true/*ignore_vertical*/);
} // loadBoundingBoxNodes

View File

@@ -62,12 +62,18 @@ protected:
void createQuad(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2,
const Vec3 &p3, unsigned int node_index,
bool invisible, bool ai_ignore, bool is_arena);
// ------------------------------------------------------------------------
/** Map 4 bounding box points to 4 closest graph nodes. */
void loadBoundingBoxNodes();
private:
/** The 2d bounding box, used for hashing. */
Vec3 m_bb_min;
Vec3 m_bb_max;
/** The 4 closest graph nodes to the bounding box. */
int m_bb_nodes[4];
RTT* m_new_rtt;
/** The node of the graph mesh. */
@@ -149,6 +155,12 @@ public:
const int curr_sector = UNKNOWN_SECTOR,
std::vector<int> *all_sectors = NULL,
bool ignore_vertical = false) const;
// ------------------------------------------------------------------------
const Vec3& getBBMin() const { return m_bb_min; }
// ------------------------------------------------------------------------
const Vec3& getBBMax() const { return m_bb_max; }
// ------------------------------------------------------------------------
const int* getBBNodes() const { return m_bb_nodes; }
}; // Graph