Make ArenaAI use only new graph interface

This commit is contained in:
Benau 2016-09-16 09:22:57 +08:00
parent 1491236e84
commit 05d2d05f2a
7 changed files with 114 additions and 112 deletions

View File

@ -25,6 +25,7 @@
#include "modes/easter_egg_hunt.hpp"
#include "modes/three_strikes_battle.hpp"
#include "modes/world.hpp"
#include "tracks/arena_graph.hpp"
#include "tracks/graph_node.hpp"
#include "tracks/quad_graph.hpp"
#include "tracks/track.hpp"
@ -134,23 +135,17 @@ void Item::initItem(ItemType type, const Vec3 &xyz)
}
// Now determine in which quad this item is, and its distance
// from the center within this quad.
m_graph_node = QuadGraph::UNKNOWN_SECTOR;
QuadGraph* currentQuadGraph = QuadGraph::get();
m_graph_node = Graph::UNKNOWN_SECTOR;
m_distance_from_center = 9999.9f;
m_avoidance_points[0] = NULL;
m_avoidance_points[1] = NULL;
// Check that QuadGraph exist (it might not in battle mode for eg)
if (currentQuadGraph != NULL)
// Check that Graph exist (it might not in battle mode without navmesh)
if (Graph::get())
{
QuadGraph::get()->findRoadSector(xyz, &m_graph_node);
Graph::get()->findRoadSector(xyz, &m_graph_node);
}
if(m_graph_node==QuadGraph::UNKNOWN_SECTOR)
{
m_graph_node = -1;
m_distance_from_center = 9999.9f; // is not used
m_avoidance_points[0] = NULL;
m_avoidance_points[1] = NULL;
}
else
else if (!ArenaGraph::get()) // Todo replace with driveline graph
{
// Item is on quad graph. Pre-compute the distance from center
// of this item, which is used by the AI (mostly for avoiding items)

View File

@ -32,9 +32,10 @@
#include "modes/linear_world.hpp"
#include "network/network_config.hpp"
#include "network/race_event_manager.hpp"
#include "tracks/arena_graph.hpp"
#include "tracks/battle_graph.hpp"
#include "tracks/graph.hpp"
#include "tracks/graph_node.hpp"
#include "tracks/quad_graph.hpp"
#include "tracks/track.hpp"
#include "utils/string_utils.hpp"
@ -158,12 +159,12 @@ ItemManager::ItemManager()
m_switch_to.push_back((Item::ItemType)i);
setSwitchItems(stk_config->m_switch_items);
if(QuadGraph::get())
if(Graph::get())
{
m_items_in_quads = new std::vector<AllItemTypes>;
// Entries 0 to n-1 are for the quads, entry
// n is for all items that are not on a quad.
m_items_in_quads->resize(QuadGraph::get()->getNumNodes()+1);
m_items_in_quads->resize(Graph::get()->getNumNodes()+1);
}
else
{
@ -228,8 +229,7 @@ void ItemManager::insertItem(Item *item)
// If the item is on the driveline, store it at the appropriate index
if(graph_node > -1)
{
int sector = QuadGraph::get()->getNode(graph_node)->getNodeIndex();
(*m_items_in_quads)[sector].push_back(item);
(*m_items_in_quads)[graph_node].push_back(item);
}
else // otherwise store it in the 'outside' index
(*m_items_in_quads)[m_items_in_quads->size()-1].push_back(item);
@ -427,9 +427,8 @@ void ItemManager::deleteItem(Item *item)
if(m_items_in_quads)
{
const Vec3 &xyz = item->getXYZ();
int sector = QuadGraph::UNKNOWN_SECTOR;
QuadGraph::get()->findRoadSector(xyz, &sector);
unsigned int indx = sector==QuadGraph::UNKNOWN_SECTOR
int sector = item->getGraphNode();
unsigned int indx = sector==Graph::UNKNOWN_SECTOR
? (unsigned int) m_items_in_quads->size()-1
: sector;
AllItemTypes &items = (*m_items_in_quads)[indx];

View File

@ -132,6 +132,16 @@ public:
assert(n<(*m_items_in_quads).size());
return (*m_items_in_quads)[n];
} // getItemsInQuads
// ------------------------------------------------------------------------
/** Returns the first item (NULL if none) on the specified quad
*/
Item* getFirstItemInQuad(unsigned int n) const
{
assert(m_items_in_quads);
assert(n < m_items_in_quads->size());
return ((*m_items_in_quads)[n]).empty() ? NULL :
(*m_items_in_quads)[n].front();
} // getFirstItemInQuad
}; // ItemManager
#endif

View File

@ -26,11 +26,11 @@
#include "karts/controller/player_controller.hpp"
#include "karts/controller/ai_properties.hpp"
#include "karts/kart_properties.hpp"
#include "tracks/battle_graph.hpp"
#include "tracks/quad.hpp"
#include "tracks/arena_graph.hpp"
#include "tracks/arena_node.hpp"
#include "utils/log.hpp"
int ArenaAI::m_test_node_for_banana = BattleGraph::UNKNOWN_POLY;
int ArenaAI::m_test_node_for_banana = Graph::UNKNOWN_SECTOR;
bool isNodeWithBanana(const std::pair<const Item*, int>& item_pair)
{
@ -44,6 +44,8 @@ ArenaAI::ArenaAI(AbstractKart *kart)
{
m_debug_sphere = NULL;
m_debug_sphere_next = NULL;
m_graph = ArenaGraph::get();
assert(m_graph != NULL);
} // ArenaAI
//-----------------------------------------------------------------------------
@ -51,18 +53,18 @@ ArenaAI::ArenaAI(AbstractKart *kart)
*/
void ArenaAI::reset()
{
m_target_node = BattleGraph::UNKNOWN_POLY;
m_current_forward_node = BattleGraph::UNKNOWN_POLY;
m_target_node = Graph::UNKNOWN_SECTOR;
m_current_forward_node = Graph::UNKNOWN_SECTOR;
m_current_forward_point = Vec3(0, 0, 0);
m_adjusting_side = false;
m_closest_kart = NULL;
m_closest_kart_node = BattleGraph::UNKNOWN_POLY;
m_closest_kart_node = Graph::UNKNOWN_SECTOR;
m_closest_kart_point = Vec3(0, 0, 0);
m_closest_kart_pos_data = {0};
m_cur_kart_pos_data = {0};
m_is_stuck = false;
m_is_uturn = false;
m_avoiding_banana = false;
m_avoiding_item = false;
m_target_point = Vec3(0, 0, 0);
m_time_since_last_shot = 0.0f;
m_time_since_driving = 0.0f;
@ -88,7 +90,7 @@ void ArenaAI::update(float dt)
// This is used to enable firing an item backwards.
m_controls->m_look_back = false;
m_controls->m_nitro = false;
m_avoiding_banana = false;
m_avoiding_item = false;
// Don't do anything if there is currently a kart animations shown.
if (m_kart->getKartAnimation())
@ -140,24 +142,29 @@ bool ArenaAI::updateAimingPosition()
// to compensate the time difference between steering
m_current_forward_point =
m_kart->getTrans()(Vec3(0, 0, m_kart->getKartLength()));
m_current_forward_node = BattleGraph::get()->pointToNode
(m_current_forward_node, m_current_forward_point,
false/*ignore_vertical*/);
std::vector<int>* test_nodes = NULL;
if (m_current_forward_node != Graph::UNKNOWN_SECTOR)
{
test_nodes =
m_graph->getNode(m_current_forward_node)->getNearbyNodes();
}
m_graph->findRoadSector(m_current_forward_point, &m_current_forward_node,
test_nodes);
// Use current node if forward node is unknown, or near the target
const int forward = (m_current_forward_node == BattleGraph::UNKNOWN_POLY ||
const int forward = (m_current_forward_node == Graph::UNKNOWN_SECTOR ||
m_current_forward_node == m_target_node ||
getCurrentNode() == m_target_node ? getCurrentNode() :
m_current_forward_node);
if (forward == BattleGraph::UNKNOWN_POLY ||
m_target_node == BattleGraph::UNKNOWN_POLY)
if (forward == Graph::UNKNOWN_SECTOR ||
m_target_node == Graph::UNKNOWN_SECTOR)
return false;
if (forward == m_target_node)
{
m_aiming_points.push_back(BattleGraph::get()
->getQuadOfNode(forward).getCenter());
m_aiming_points.push_back(m_graph->getNode(forward)->getCenter());
m_aiming_points.push_back(m_target_point);
m_aiming_nodes.insert(forward);
@ -165,19 +172,16 @@ bool ArenaAI::updateAimingPosition()
return true;
}
const int next_node = BattleGraph::get()
->getNextShortestPathPoly(forward, m_target_node);
if (next_node == BattleGraph::UNKNOWN_POLY)
const int next_node = m_graph->getNextNode(forward, m_target_node);
if (next_node == Graph::UNKNOWN_SECTOR)
{
Log::error("ArenaAI", "Next node is unknown, did you forget to link"
"adjacent face in navmesh?");
return false;
}
m_aiming_points.push_back(BattleGraph::get()
->getQuadOfNode(forward).getCenter());
m_aiming_points.push_back(BattleGraph::get()
->getQuadOfNode(next_node).getCenter());
m_aiming_points.push_back(m_graph->getNode(forward)->getCenter());
m_aiming_points.push_back(m_graph->getNode(next_node)->getCenter());
m_aiming_nodes.insert(forward);
m_aiming_nodes.insert(next_node);
@ -194,8 +198,8 @@ void ArenaAI::handleArenaSteering(const float dt)
{
const int current_node = getCurrentNode();
if (current_node == BattleGraph::UNKNOWN_POLY ||
m_target_node == BattleGraph::UNKNOWN_POLY)
if (current_node == Graph::UNKNOWN_SECTOR ||
m_target_node == Graph::UNKNOWN_SECTOR)
{
return;
}
@ -224,7 +228,7 @@ void ArenaAI::handleArenaSteering(const float dt)
}
else if (found_position)
{
updateBananaLocation();
updateBadItemLocation();
assert(m_aiming_points.size() == 2);
updateTurnRadius(m_kart->getXYZ(), m_aiming_points[0],
m_aiming_points[1]);
@ -368,44 +372,41 @@ bool ArenaAI::handleArenaUnstuck(const float dt)
} // handleArenaUnstuck
//-----------------------------------------------------------------------------
void ArenaAI::updateBananaLocation()
void ArenaAI::updateBadItemLocation()
{
std::vector<std::pair<const Item*, int>>& item_list =
BattleGraph::get()->getItemList();
std::set<int>::iterator node = m_aiming_nodes.begin();
while (node != m_aiming_nodes.end())
// Check if any nodes AI will cross will meet bad items
for (const int& node : m_aiming_nodes)
{
m_test_node_for_banana = *node;
std::vector<std::pair<const Item*, int>>::iterator it =
std::find_if(item_list.begin(), item_list.end(), isNodeWithBanana);
assert(node != Graph::UNKNOWN_SECTOR);
Item* selected = ItemManager::get()->getFirstItemInQuad(node);
if (it != item_list.end())
if (selected && !selected->wasCollected() &&
(selected->getType() == Item::ITEM_BANANA ||
selected->getType() == Item::ITEM_BUBBLEGUM ||
selected->getType() == Item::ITEM_BUBBLEGUM_NOLOK))
{
Vec3 banana_lc;
checkPosition(it->first->getXYZ(), NULL, &banana_lc,
Vec3 bad_item_lc;
checkPosition(selected->getXYZ(), NULL, &bad_item_lc,
true/*use_front_xyz*/);
// If satisfy the below condition, AI should not eat banana:
// banana_lc.z() < 0.0f, behind the kart
if (banana_lc.z() < 0.0f)
// If satisfy the below condition, AI should not be affected by it:
// bad_item_lc.z() < 0.0f, behind the kart
if (bad_item_lc.z() < 0.0f)
{
node++;
continue;
}
// If the node AI will pass has a banana, adjust the aim position
banana_lc = (banana_lc.x() < 0 ? banana_lc + Vec3(5, 0, 0) :
banana_lc - Vec3(5, 0, 0));
m_aiming_points[1] = m_kart->getTrans()(banana_lc);
m_avoiding_banana = true;
// If the node AI will pass has a bad item, adjust the aim position
bad_item_lc = (bad_item_lc.x() < 0 ? bad_item_lc + Vec3(5, 0, 0) :
bad_item_lc - Vec3(5, 0, 0));
m_aiming_points[1] = m_kart->getTrans()(bad_item_lc);
m_avoiding_item = true;
// Handle one banana only
return;
}
node++;
}
} // updateBananaLocation
} // updateBadItemLocation
//-----------------------------------------------------------------------------
/** This function handles braking. It used the turn radius found by
@ -429,8 +430,8 @@ void ArenaAI::handleArenaBraking()
m_controls->m_brake = false;
if (getCurrentNode() == BattleGraph::UNKNOWN_POLY ||
m_target_node == BattleGraph::UNKNOWN_POLY) return;
if (getCurrentNode() == Graph::UNKNOWN_SECTOR ||
m_target_node == Graph::UNKNOWN_SECTOR) return;
if (m_aiming_points.empty()) return;
@ -658,55 +659,50 @@ void ArenaAI::handleArenaItems(const float dt)
//-----------------------------------------------------------------------------
void ArenaAI::collectItemInArena(Vec3* aim_point, int* target_node) const
{
float distance = 99999.9f;
const std::vector< std::pair<const Item*, int> >& item_list =
BattleGraph::get()->getItemList();
const unsigned int items_count = item_list.size();
float distance = 999999.9f;
Item* selected = (*target_node == Graph::UNKNOWN_SECTOR ? NULL :
ItemManager::get()->getFirstItemInQuad(*target_node));
if (item_list.empty())
// Don't look for a new item unless it's collected or swapped
if (selected && !(selected->wasCollected() ||
selected->getType() == Item::ITEM_BANANA ||
selected->getType() == Item::ITEM_BUBBLEGUM ||
selected->getType() == Item::ITEM_BUBBLEGUM_NOLOK))
{
// Notice: this should not happen, as it makes no sense
// for an arean without items, if so how can attack happen?
Log::fatal ("ArenaAI",
"AI can't find any items in the arena, "
"maybe there is something wrong with the navmesh, "
"make sure it lies closely to the ground.");
*aim_point = selected->getXYZ();
return;
}
unsigned int closest_item_num = 0;
for (unsigned int i = 0; i < items_count; ++i)
for (unsigned int i = 0; i < m_graph->getNumNodes(); i++)
{
const Item* item = item_list[i].first;
Item* cur_item = ItemManager::get()->getFirstItemInQuad(i);
if (cur_item == NULL) continue;
if (cur_item->wasCollected() ||
cur_item->getType() == Item::ITEM_BANANA ||
cur_item->getType() == Item::ITEM_BUBBLEGUM ||
cur_item->getType() == Item::ITEM_BUBBLEGUM_NOLOK)
continue;
if (item->wasCollected()) continue;
if ((item->getType() == Item::ITEM_NITRO_BIG ||
item->getType() == Item::ITEM_NITRO_SMALL) &&
if ((cur_item->getType() == Item::ITEM_NITRO_BIG ||
cur_item->getType() == Item::ITEM_NITRO_SMALL) &&
(m_kart->getEnergy() >
m_kart->getKartProperties()->getNitroSmallContainer()))
continue; // Ignore nitro when already has some
float test_distance = BattleGraph::get()
->getDistance(item_list[i].second, getCurrentNode());
if (test_distance <= distance &&
(item->getType() == Item::ITEM_BONUS_BOX ||
item->getType() == Item::ITEM_NITRO_BIG ||
item->getType() == Item::ITEM_NITRO_SMALL))
const int cur_node = cur_item->getGraphNode();
assert(cur_node != Graph::UNKNOWN_SECTOR);
float test_distance = m_graph->getDistance(cur_node, getCurrentNode());
if (test_distance <= distance)
{
closest_item_num = i;
selected = cur_item;
distance = test_distance;
}
}
const Item *item_selected = item_list[closest_item_num].first;
if (item_selected->getType() == Item::ITEM_BONUS_BOX ||
item_selected->getType() == Item::ITEM_NITRO_BIG ||
item_selected->getType() == Item::ITEM_NITRO_SMALL)
if (selected != NULL)
{
*aim_point = item_selected->getXYZ();
*target_node = item_list[closest_item_num].second;
*aim_point = selected->getXYZ();
*target_node = selected->getGraphNode();
}
else
{

View File

@ -27,7 +27,7 @@
#include "graphics/irr_driver.hpp"
#endif
class Vec3;
class ArenaGraph;
namespace irr
{
@ -63,11 +63,13 @@ protected:
/** The target point. */
Vec3 m_target_point;
bool m_avoiding_banana;
bool m_avoiding_item;
void collectItemInArena(Vec3*, int*) const;
float findAngleFrom3Edges(float a, float b, float c);
private:
ArenaGraph* m_graph;
/** Used by handleArenaUTurn, it tells whether to do left or right
* turning when steering is overridden. */
bool m_adjusting_side;
@ -115,7 +117,7 @@ private:
void handleArenaUTurn(const float dt);
bool handleArenaUnstuck(const float dt);
bool updateAimingPosition();
void updateBananaLocation();
void updateBadItemLocation();
void updateTurnRadius(const Vec3& p1, const Vec3& p2,
const Vec3& p3);
virtual int getCurrentNode() const = 0;
@ -123,7 +125,7 @@ private:
virtual void resetAfterStop() {};
virtual void findClosestKart(bool use_difficulty) = 0;
virtual void findTarget() = 0;
virtual bool forceBraking() { return m_avoiding_banana; }
virtual bool forceBraking() { return m_avoiding_item; }
virtual bool ignorePathFinding() { return false; }
public:
static int m_test_node_for_banana;

View File

@ -67,7 +67,7 @@ private:
virtual bool isWaiting() const;
virtual bool canSkid(float steer_fraction) { return false; }
virtual bool forceBraking() OVERRIDE
{ return m_avoiding_banana || m_force_brake; }
{ return m_avoiding_item || m_force_brake; }
virtual bool ignorePathFinding() OVERRIDE
{ return m_overtake_ball || m_chasing_ball; }
public:

View File

@ -280,7 +280,7 @@ void Track::reset()
void Track::cleanup()
{
QuadGraph::destroy();
BattleGraph::destroy();
Graph::destroy();
ItemManager::destroy();
VAOManager::kill();
@ -678,7 +678,7 @@ void Track::loadBattleGraph(const XMLNode &node)
ArenaGraph* graph = new ArenaGraph(m_root+"navmesh.xml", &node);
Graph::setGraph(graph);
if(BattleGraph::get()->getNumNodes()==0)
if(Graph::get()->getNumNodes()==0)
{
Log::warn("track", "No graph nodes defined for track '%s'\n",
m_filename.c_str());