Backwards firing and hard u-turn for backward node
TODO: correct unstuck and perfect angle fire?
This commit is contained in:
parent
aa9220772f
commit
c910c19827
@ -21,9 +21,9 @@
|
||||
#undef AI_DEBUG
|
||||
#include "karts/controller/battle_ai.hpp"
|
||||
|
||||
#ifdef AI_DEBUG
|
||||
//#ifdef AI_DEBUG
|
||||
#include "graphics/irr_driver.hpp"
|
||||
#endif
|
||||
//#endif
|
||||
|
||||
#include "items/attachment.hpp"
|
||||
#include "items/item_manager.hpp"
|
||||
@ -55,6 +55,7 @@ using namespace irr;
|
||||
#endif
|
||||
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
BattleAI::BattleAI(AbstractKart *kart,
|
||||
StateManager::ActivePlayer *player)
|
||||
@ -63,12 +64,12 @@ 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)
|
||||
{
|
||||
@ -93,9 +94,9 @@ BattleAI::BattleAI(AbstractKart *kart,
|
||||
|
||||
BattleAI::~BattleAI()
|
||||
{
|
||||
#ifdef AI_DEBUG
|
||||
//#ifdef AI_DEBUG
|
||||
irr_driver->removeNode(m_debug_sphere);
|
||||
#endif
|
||||
//#endif
|
||||
} // ~BattleAI
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -105,12 +106,23 @@ void BattleAI::reset()
|
||||
{
|
||||
m_current_node = BattleGraph::UNKNOWN_POLY;
|
||||
m_target_node = BattleGraph::UNKNOWN_POLY;
|
||||
m_closest_kart_node = BattleGraph::UNKNOWN_POLY;
|
||||
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_target_point = Vec3(0,0,0);
|
||||
m_time_since_last_shot = 0.0f;
|
||||
m_time_since_reversing = 0.0f;
|
||||
m_time_since_stuck = 0.0f;
|
||||
m_currently_reversing = false;
|
||||
m_closest_kart_distance = 99999.9f;
|
||||
m_time_since_uturn = 0.0f;
|
||||
m_on_node.clear();
|
||||
m_path_corners.clear();
|
||||
m_portals.clear();
|
||||
|
||||
AIBaseController::reset();
|
||||
}
|
||||
} // reset
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** This is the main entry point for the AI.
|
||||
@ -119,29 +131,168 @@ void BattleAI::reset()
|
||||
*/
|
||||
void BattleAI::update(float dt)
|
||||
{
|
||||
// This is used to enable firing an item backwards.
|
||||
m_controls->m_look_back = false;
|
||||
m_controls->m_nitro = false;
|
||||
|
||||
if (m_world->isStartPhase())
|
||||
{
|
||||
AIBaseController::update(dt);
|
||||
return;
|
||||
}
|
||||
// Don't do anything if there is currently a kart animations shown.
|
||||
if(m_kart->getKartAnimation())
|
||||
return;
|
||||
|
||||
handleAcceleration(dt);
|
||||
handleSteering(dt);
|
||||
if (m_world->isStartPhase())
|
||||
{
|
||||
AIBaseController::update(dt);
|
||||
return;
|
||||
}
|
||||
|
||||
checkIfStuck(dt);
|
||||
if (m_is_stuck && !m_is_uturn)
|
||||
{
|
||||
cout <<"correct"<<endl;
|
||||
m_controls->m_accel = -1.0f;
|
||||
setSteering(1.0f,dt);
|
||||
m_time_since_reversing += dt;
|
||||
|
||||
if (m_time_since_reversing >= 0.6f)
|
||||
{
|
||||
cout <<"correctfinished"<<endl;
|
||||
m_controls->m_accel = 1.0f;
|
||||
m_is_stuck = false;
|
||||
m_time_since_reversing = 0.0f;
|
||||
}
|
||||
AIBaseController::update(dt);
|
||||
return;
|
||||
}
|
||||
|
||||
findClosestKart();
|
||||
findTarget();
|
||||
handleItems(dt);
|
||||
handleBraking();
|
||||
handleGetUnstuck(dt);
|
||||
|
||||
if (m_kart->getSpeed() > 15.0f)
|
||||
m_controls->m_nitro = true;
|
||||
|
||||
if (m_is_uturn)
|
||||
{
|
||||
handleUTurn(dt);
|
||||
}
|
||||
else
|
||||
{
|
||||
handleAcceleration(dt);
|
||||
handleSteering(dt);
|
||||
handleBraking();
|
||||
}
|
||||
|
||||
AIBaseController::update(dt);
|
||||
|
||||
} //update
|
||||
} // update
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void BattleAI::checkIfStuck(const float dt)
|
||||
{
|
||||
if (m_is_stuck) return;
|
||||
|
||||
// Check if current kart is stuck
|
||||
if (m_kart->getSpeed() < 2.0f && !m_kart->getKartAnimation() &&
|
||||
!m_world->isStartPhase() && !m_is_uturn)
|
||||
{
|
||||
m_time_since_stuck += dt;
|
||||
m_on_node.insert(m_current_node);
|
||||
}
|
||||
|
||||
if (m_time_since_stuck >= 2.0f)
|
||||
{
|
||||
if (m_on_node.size() > 2)
|
||||
{
|
||||
cout<<m_on_node.size()<<endl;
|
||||
// Reset timer to zero for any correct movement
|
||||
m_time_since_stuck = 0.0f;
|
||||
return;
|
||||
}
|
||||
cout<<"stuck"<<endl;
|
||||
m_on_node.clear();
|
||||
m_time_since_stuck = 0.0f;
|
||||
m_is_stuck = true;
|
||||
}
|
||||
|
||||
} // checkIfStuck
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void BattleAI::checkPosition(const Vec3 &point, posData *pos_data)
|
||||
{
|
||||
btQuaternion q(btVector3(0,1,0), -m_kart->getHeading());
|
||||
Vec3 p = point - m_kart->getXYZ();
|
||||
Vec3 lc = quatRotate(q, p);
|
||||
|
||||
if (lc.getZ() < 0)
|
||||
pos_data->behind = true;
|
||||
else
|
||||
pos_data->behind = false;
|
||||
|
||||
pos_data->angle = atan2(point.getX(), point.getZ());
|
||||
pos_data->distance = p.length_2d();
|
||||
} // checkPosition
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void BattleAI::findClosestKart()
|
||||
{
|
||||
float distance = 99999.9f;
|
||||
const unsigned int n = m_world->getNumKarts();
|
||||
int closest_kart_num = 0;
|
||||
|
||||
for (unsigned int i = 0; i < n; i++)
|
||||
{
|
||||
const AbstractKart* kart = m_world->getKart(i);
|
||||
if (kart->isEliminated()) continue;
|
||||
|
||||
if (kart->getWorldKartId() == m_kart->getWorldKartId())
|
||||
continue; // Skip the same kart
|
||||
|
||||
Vec3 d = kart->getXYZ() - m_kart->getXYZ();
|
||||
if (d.length_2d() <= distance)
|
||||
{
|
||||
distance = d.length_2d();
|
||||
closest_kart_num = i;
|
||||
}
|
||||
}
|
||||
|
||||
const AbstractKart* closest_kart = m_world->getKart(closest_kart_num);
|
||||
if (!closest_kart->getController()->isPlayerController())
|
||||
{
|
||||
BattleAI* controller = (BattleAI*)(closest_kart->getController());
|
||||
m_closest_kart_node = controller->getCurrentNode();
|
||||
m_closest_kart_point = closest_kart->getXYZ();
|
||||
}
|
||||
|
||||
else if (closest_kart->getController()->isPlayerController())
|
||||
{
|
||||
PlayerController* controller = (PlayerController*)(closest_kart->getController());
|
||||
m_closest_kart_node = controller->getCurrentNode();
|
||||
m_closest_kart_point = closest_kart->getXYZ();
|
||||
}
|
||||
checkPosition(m_closest_kart_point, &m_closest_kart_pos_data);
|
||||
} // findClosestKart
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void BattleAI::findTarget()
|
||||
{
|
||||
// Find a suitable target to drive to, either powerup or kart
|
||||
if (m_kart->getPowerup()->getType() == PowerupManager::POWERUP_NOTHING &&
|
||||
m_kart->getAttachment()->getType() != Attachment::ATTACH_SWATTER)
|
||||
handleItemCollection(&m_target_point , &m_target_node);
|
||||
else
|
||||
{
|
||||
m_target_point = m_closest_kart_point;
|
||||
m_target_node = m_closest_kart_node;
|
||||
}
|
||||
} // findTarget
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Handles acceleration.
|
||||
* \param dt Time step size.
|
||||
*/
|
||||
void BattleAI::handleAcceleration( const float dt)
|
||||
void BattleAI::handleAcceleration(const float dt)
|
||||
{
|
||||
if(m_controls->m_brake)
|
||||
if (m_controls->m_brake)
|
||||
{
|
||||
m_controls->m_accel = 0.0f;
|
||||
return;
|
||||
@ -150,133 +301,80 @@ void BattleAI::handleAcceleration( const float dt)
|
||||
|
||||
} // handleAcceleration
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void BattleAI::handleUTurn(const float dt)
|
||||
{
|
||||
m_controls->m_accel = -2.0f;
|
||||
if (m_time_since_uturn >= 1.0f)
|
||||
setSteering(M_PI,dt); // Preventing keep going around circle
|
||||
else
|
||||
setSteering(-M_PI,dt);
|
||||
m_time_since_uturn += dt;
|
||||
|
||||
checkPosition(m_target_point, &m_cur_kart_pos_data);
|
||||
if (!m_cur_kart_pos_data.behind || m_time_since_uturn >= 1.5f)
|
||||
{
|
||||
m_is_uturn = false;
|
||||
m_controls->m_accel = 2.0f;
|
||||
m_time_since_uturn = 0.0f;
|
||||
}
|
||||
} // handleUTurn
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** This function sets the steering.
|
||||
* \param dt Time step size.
|
||||
*/
|
||||
void BattleAI::handleSteering(const float dt)
|
||||
{
|
||||
if (m_current_node == BattleGraph::UNKNOWN_POLY) return;
|
||||
if (m_current_node == BattleGraph::UNKNOWN_POLY ||
|
||||
m_target_node == BattleGraph::UNKNOWN_POLY) return;
|
||||
|
||||
if (m_kart->getPowerup()->getType()==PowerupManager::POWERUP_NOTHING)
|
||||
if (m_target_node == m_current_node)
|
||||
{
|
||||
handleItemCollection(&m_target_point , &m_target_node);
|
||||
if (m_target_node == BattleGraph::UNKNOWN_POLY) return;
|
||||
|
||||
if (m_target_node != m_current_node)
|
||||
// Very close to the item, steer directly
|
||||
checkPosition(m_target_point, &m_cur_kart_pos_data);
|
||||
m_debug_sphere->setPosition(m_target_point.toIrrVector());
|
||||
if (m_cur_kart_pos_data.behind)
|
||||
{
|
||||
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;
|
||||
}
|
||||
m_is_uturn = true;
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
// Do nothing if no targets found
|
||||
m_target_node = 0;
|
||||
m_target_point = 0.0f;
|
||||
setSteering(0.0f,dt);
|
||||
return;
|
||||
float target_angle = steerToPoint(m_target_point);
|
||||
setSteering(target_angle,dt);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// After this AI kart has a powerup, try to follow a closest kart in the map
|
||||
findClosestKart(&m_target_point , &m_target_node);
|
||||
if (m_target_node == BattleGraph::UNKNOWN_POLY) return;
|
||||
|
||||
if (m_target_node != m_current_node)
|
||||
else 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_target_point = m_path_corners[0];
|
||||
|
||||
checkPosition(m_target_point, &m_cur_kart_pos_data);
|
||||
m_debug_sphere->setPosition(m_target_point.toIrrVector());
|
||||
if (m_cur_kart_pos_data.behind)
|
||||
{
|
||||
m_is_uturn = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
//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);
|
||||
// Do nothing (go straight) if no targets found
|
||||
setSteering(1.0f,dt);
|
||||
return;
|
||||
}
|
||||
} // 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->getWorldKartId() == m_kart->getWorldKartId())
|
||||
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
|
||||
@ -379,7 +477,8 @@ void BattleAI::stringPull(const Vec3& start_pos, const Vec3& end_pos)
|
||||
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;
|
||||
@ -399,7 +498,8 @@ 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;
|
||||
@ -422,34 +522,7 @@ void BattleAI::stringPull(const Vec3& start_pos, const Vec3& end_pos)
|
||||
|
||||
//Push end_pos to m_path_corners so if no corners, we aim at target
|
||||
m_path_corners.push_back(end_pos);
|
||||
} // stringPull
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Calls AIBaseController::isStuck() to determine if the AI is stuck.
|
||||
* If the AI is stuck then it will override the controls and start reverse
|
||||
* the kart while turning.
|
||||
*/
|
||||
void BattleAI::handleGetUnstuck(const float dt)
|
||||
{
|
||||
if (isStuck() == true)
|
||||
{
|
||||
m_time_since_stuck = 0.0f;
|
||||
m_currently_reversing = true;
|
||||
m_controls->reset();
|
||||
}
|
||||
if (m_currently_reversing == true)
|
||||
{
|
||||
m_controls->m_accel = -0.35f;
|
||||
setSteering(-M_PI,dt);
|
||||
m_time_since_stuck += dt;
|
||||
|
||||
if(m_time_since_stuck >= 0.6f)
|
||||
{
|
||||
m_currently_reversing = false;
|
||||
m_time_since_stuck = 0.0f;
|
||||
}
|
||||
}
|
||||
} // handleGetUnstuck
|
||||
} // stringPull
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** This function handles braking. It calls determineTurnRadius() to find out
|
||||
@ -468,8 +541,8 @@ void BattleAI::handleBraking()
|
||||
|
||||
std::vector<Vec3> points;
|
||||
|
||||
if (m_current_node == -1 || m_target_node == -1)
|
||||
return;
|
||||
if (m_current_node == BattleGraph::UNKNOWN_POLY ||
|
||||
m_target_node == BattleGraph::UNKNOWN_POLY) return;
|
||||
|
||||
points.push_back(m_kart->getXYZ());
|
||||
points.push_back(m_path_corners[0]);
|
||||
@ -477,7 +550,8 @@ void BattleAI::handleBraking()
|
||||
|
||||
float current_curve_radius = BattleAI::determineTurnRadius(points);
|
||||
|
||||
Vec3 d1 = m_kart->getXYZ() - m_target_point; Vec3 d2 = m_kart->getXYZ() - m_path_corners[0];
|
||||
Vec3 d1 = m_kart->getXYZ() - m_target_point;
|
||||
Vec3 d2 = m_kart->getXYZ() - m_path_corners[0];
|
||||
if (d1.length2_2d() < d2.length2_2d())
|
||||
current_curve_radius = d1.length_2d();
|
||||
|
||||
@ -485,20 +559,12 @@ void BattleAI::handleBraking()
|
||||
m_kart->getKartProperties()
|
||||
->getSpeedForTurnRadius(current_curve_radius);
|
||||
|
||||
if (m_kart->getSpeed() > max_turn_speed &&
|
||||
m_kart->getSpeed()>MIN_SPEED )// &&
|
||||
//fabsf(m_controls->m_steer) > 0.95f)
|
||||
if (m_kart->getSpeed() > max_turn_speed &&
|
||||
m_kart->getSpeed() > MIN_SPEED)
|
||||
{
|
||||
m_controls->m_brake = true;
|
||||
#ifdef DEBUG
|
||||
if(m_ai_debug)
|
||||
Log::debug("BattleAI",
|
||||
"speed %f too tight curve: radius %f ",
|
||||
m_kart->getSpeed(),
|
||||
m_kart->getIdent().c_str(),
|
||||
current_curve_radius);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // handleBraking
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -555,39 +621,14 @@ float BattleAI::determineTurnRadius( std::vector<Vec3>& points )
|
||||
float radius = pow(abs(1 + pow(dx_by_dz,2)),1.5f)/ abs(d2x_by_dz);
|
||||
|
||||
return radius;
|
||||
}
|
||||
} // determineTurnRadius
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Alternative implementation of isStuck()
|
||||
/*
|
||||
float BattleAI::isStuck(const float dt)
|
||||
{
|
||||
// check if kart is stuck
|
||||
if(m_kart->getSpeed()<2.0f && !m_kart->getKartAnimation() &&
|
||||
!m_world->isStartPhase())
|
||||
{
|
||||
m_time_since_stuck += dt;
|
||||
if(m_time_since_stuck > 2.0f)
|
||||
{
|
||||
return true;
|
||||
m_time_since_stuck=0.0f;
|
||||
} // m_time_since_stuck > 2.0f
|
||||
}
|
||||
else
|
||||
{
|
||||
m_time_since_stuck = 0.0f;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void BattleAI::handleItems(const float dt)
|
||||
{
|
||||
m_controls->m_fire = false;
|
||||
if (m_kart->getPowerup()->getType() == PowerupManager::POWERUP_NOTHING)
|
||||
if (m_kart->getKartAnimation() ||
|
||||
m_kart->getPowerup()->getType() == PowerupManager::POWERUP_NOTHING)
|
||||
return;
|
||||
|
||||
m_time_since_last_shot += dt;
|
||||
@ -618,13 +659,11 @@ void BattleAI::handleItems(const float dt)
|
||||
// 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)
|
||||
// Use bubblegum if the next kart behind is 'close' but not too close,
|
||||
// or can't find a close kart for too long time
|
||||
if ((m_closest_kart_pos_data.distance < 15.0f &&
|
||||
m_closest_kart_pos_data.distance > 3.0f) ||
|
||||
m_time_since_last_shot > 15.0f)
|
||||
{
|
||||
m_controls->m_fire = true;
|
||||
m_controls->m_look_back = true;
|
||||
@ -633,20 +672,24 @@ void BattleAI::handleItems(const float dt)
|
||||
|
||||
break; // POWERUP_BUBBLEGUM
|
||||
}
|
||||
// All the thrown/fired items might be improved by considering the angle
|
||||
// towards m_kart_ahead.
|
||||
// FIXME:: All the thrown/fired items might be improved by considering
|
||||
// the angle towards (m_closest_kart_pos_data.angle).
|
||||
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)
|
||||
// Leave some time between shots
|
||||
if (m_time_since_last_shot < 1.0f) break;
|
||||
|
||||
if (m_closest_kart_pos_data.distance < 25.0f)
|
||||
{
|
||||
m_controls->m_fire = true;
|
||||
m_controls->m_look_back = false;
|
||||
if (m_closest_kart_pos_data.behind)
|
||||
m_controls->m_look_back = true;
|
||||
else
|
||||
m_controls->m_look_back = false;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -658,15 +701,17 @@ void BattleAI::handleItems(const float dt)
|
||||
// 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)
|
||||
// Leave some time between shots
|
||||
if (m_time_since_last_shot < 1.0f) break;
|
||||
|
||||
if (m_closest_kart_pos_data.distance < 5.0f)
|
||||
{
|
||||
m_controls->m_fire = true;
|
||||
m_controls->m_look_back = false;
|
||||
if (m_closest_kart_pos_data.behind)
|
||||
m_controls->m_look_back = true;
|
||||
else
|
||||
m_controls->m_look_back = false;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -679,7 +724,7 @@ void BattleAI::handleItems(const float dt)
|
||||
if(m_kart->getShieldTime() > min_bubble_time)
|
||||
break;
|
||||
|
||||
if (m_closest_kart_distance < 5.0f)
|
||||
if (m_closest_kart_pos_data.distance < 5.0f)
|
||||
{
|
||||
m_controls->m_fire = true;
|
||||
m_controls->m_look_back = false;
|
||||
@ -715,42 +760,39 @@ void BattleAI::handleItems(const float dt)
|
||||
assert(false);
|
||||
}
|
||||
if (m_controls->m_fire)
|
||||
{
|
||||
m_closest_kart_distance = 99999.9f;
|
||||
m_time_since_last_shot = 0.0f;
|
||||
}
|
||||
}
|
||||
m_time_since_last_shot = 0.0f;
|
||||
} // handleItems
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void BattleAI::handleItemCollection(Vec3* aim_point, int* target_node)
|
||||
{
|
||||
float distance = 5.0f;
|
||||
bool found_suitable_item = false;
|
||||
float distance = 99999.9f;
|
||||
const std::vector< std::pair<Item*, int> >& item_list =
|
||||
BattleGraph::get()->getItemList();
|
||||
unsigned int items_count = item_list.size();
|
||||
unsigned int closest_item_num = 0;
|
||||
|
||||
for (unsigned int j = 0; j < 50; j++)
|
||||
for (unsigned int i = 0; i < items_count; ++i)
|
||||
{
|
||||
for (unsigned int i = 0; i < items_count; ++i)
|
||||
Item* item = item_list[i].first;
|
||||
if ((item->getType() == Item::ITEM_NITRO_BIG ||
|
||||
item->getType() == Item::ITEM_NITRO_SMALL) &&
|
||||
((m_kart->getKartProperties()->getNitroSmallContainer() +
|
||||
m_kart->getKartProperties()->getNitroBigContainer()) > 1.0f))
|
||||
continue; // Ignore nitro when already has some
|
||||
|
||||
Vec3 d = item->getXYZ() - m_kart->getXYZ();
|
||||
if (d.length_2d() <= distance && (item->getType() ==
|
||||
Item::ITEM_BONUS_BOX || item->getType() ==
|
||||
Item::ITEM_NITRO_BIG || item->getType() ==
|
||||
Item::ITEM_NITRO_SMALL) && !item->wasCollected())
|
||||
{
|
||||
Item* item = item_list[i].first;
|
||||
Vec3 d = item->getXYZ() - m_kart->getXYZ();
|
||||
if (d.length_2d() <= distance)
|
||||
{
|
||||
if ((item->getType() == Item::ITEM_BONUS_BOX)
|
||||
&& !item->wasCollected())
|
||||
{
|
||||
m_item_to_collect = item;
|
||||
found_suitable_item = true;
|
||||
*aim_point = item->getXYZ();
|
||||
*target_node = item_list[i].second;
|
||||
break;
|
||||
}
|
||||
}
|
||||
closest_item_num = i;
|
||||
distance = d.length_2d();
|
||||
}
|
||||
if (found_suitable_item) break;
|
||||
distance = 2.0f * distance;
|
||||
}
|
||||
}
|
||||
|
||||
m_item_to_collect = item_list[closest_item_num].first;
|
||||
*aim_point = (item_list[closest_item_num].first)->getXYZ();
|
||||
*target_node = item_list[closest_item_num].second;
|
||||
} // handleItemCollection
|
||||
|
@ -45,61 +45,84 @@ class BattleAI : public AIBaseController
|
||||
|
||||
private:
|
||||
|
||||
/** Holds the position info of targets. */
|
||||
struct posData {bool behind; float angle; float distance;};
|
||||
|
||||
/** Holds the current position of the AI on the battle graph. Sets to
|
||||
* BattleGraph::UNKNOWN_POLY if the location is unknown. This variable is
|
||||
* updated in ThreeStrikesBattle::updateKartNodes() */
|
||||
* updated in ThreeStrikesBattle::updateKartNodes(). */
|
||||
int m_current_node;
|
||||
|
||||
int m_closest_kart_node;
|
||||
Vec3 m_closest_kart_point;
|
||||
|
||||
posData m_closest_kart_pos_data;
|
||||
posData m_cur_kart_pos_data;
|
||||
|
||||
/** Indicates that the kart is currently stuck, and m_time_since_stuck is
|
||||
* counting down. */
|
||||
bool m_is_stuck;
|
||||
|
||||
/** Indicates that the kart need a uturn to reach a node behind, and
|
||||
* m_time_since_uturn is counting down. */
|
||||
bool m_is_uturn;
|
||||
|
||||
const Item *m_item_to_collect;
|
||||
|
||||
/** Holds the unique node ai has walked through, useful to tell if AI is
|
||||
* stuck by determine the size of this set. */
|
||||
std::set <int> m_on_node;
|
||||
|
||||
/** Holds the corner points computed using the funnel algorithm that the AI
|
||||
* will eventaully move through. See stringPull(). */
|
||||
std::vector<Vec3> m_path_corners;
|
||||
|
||||
/** 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;
|
||||
|
||||
/** The node(poly) at which the target point lies in. */
|
||||
int m_target_node;
|
||||
|
||||
/** The target point. */
|
||||
Vec3 m_target_point;
|
||||
|
||||
/** 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;
|
||||
|
||||
/** Holds the corner points computed using the funnel algorithm that the AI
|
||||
* 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 */
|
||||
/** This is a timer that counts down when the kart is reversing to get unstuck. */
|
||||
float m_time_since_reversing;
|
||||
|
||||
/** This is a timer that counts down when the kart is starting to get stuck. */
|
||||
float m_time_since_stuck;
|
||||
|
||||
/** Indicates that the kart is currently reversing, and m_time_since_stuck is
|
||||
* counting down. */
|
||||
bool m_currently_reversing;
|
||||
|
||||
float m_closest_kart_distance;
|
||||
|
||||
const Item *m_item_to_collect;
|
||||
/** This is a timer that counts down when the kart is doing u-turn. */
|
||||
float m_time_since_uturn;
|
||||
|
||||
void checkIfStuck(const float dt);
|
||||
void checkPosition(const Vec3 &, posData*);
|
||||
float determineTurnRadius(std::vector<Vec3>& points);
|
||||
void findPortals(int start, int end);
|
||||
void stringPull(const Vec3&, const Vec3&);
|
||||
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*);
|
||||
void findClosestKart();
|
||||
void findPortals(int start, int end);
|
||||
void findTarget();
|
||||
void handleAcceleration(const float dt);
|
||||
void handleBraking();
|
||||
void handleItems(const float dt);
|
||||
void handleItemCollection(Vec3*, int*);
|
||||
void handleSteering(const float dt);
|
||||
void handleUTurn(const float dt);
|
||||
void stringPull(const Vec3&, const Vec3&);
|
||||
|
||||
protected:
|
||||
|
||||
/** Keep a pointer to world. */
|
||||
ThreeStrikesBattle *m_world;
|
||||
|
||||
#ifdef AI_DEBUG
|
||||
//#ifdef AI_DEBUG
|
||||
/** For debugging purpose: a sphere indicating where the AI
|
||||
* is targeting at. */
|
||||
irr::scene::ISceneNode *m_debug_sphere;
|
||||
#endif
|
||||
//#endif
|
||||
|
||||
public:
|
||||
BattleAI(AbstractKart *kart,
|
||||
|
@ -87,11 +87,13 @@ void BattleGraph::computeFloydWarshall()
|
||||
// AI must check this
|
||||
m_parent_poly = std::vector< std::vector<int> > (n, std::vector<int>(n,BattleGraph::UNKNOWN_POLY));
|
||||
for(unsigned int i=0; i<n; i++)
|
||||
{
|
||||
for(unsigned int j=0; j<n; j++)
|
||||
{
|
||||
if(i == j || m_distance_matrix[i][j]>=9899.9f) m_parent_poly[i][j]=-1;
|
||||
else m_parent_poly[i][j] = i;
|
||||
}
|
||||
}
|
||||
|
||||
for(unsigned int k=0; k<n; k++)
|
||||
{
|
||||
@ -256,7 +258,11 @@ void BattleGraph::findItemsOnGraphNodes(ItemManager * item_manager)
|
||||
for (unsigned int j = 0; j < this->getNumNodes(); ++j)
|
||||
{
|
||||
if (NavMesh::get()->getNavPoly(j).pointInPoly(xyz))
|
||||
polygon = j;
|
||||
{
|
||||
float dist = xyz.getY() - NavMesh::get()->getCenterOfPoly(j).getY();
|
||||
if (fabsf(dist) < 1.0f )
|
||||
polygon = j;
|
||||
}
|
||||
}
|
||||
|
||||
if (polygon != BattleGraph::UNKNOWN_POLY)
|
||||
|
Loading…
Reference in New Issue
Block a user