Significantly improve turning and bad items avoidance for ArenaAI
This commit is contained in:
parent
62dfef1fb9
commit
c434cb80f4
@ -279,3 +279,51 @@ void AIBaseController::crashed(const Material *m)
|
||||
}
|
||||
|
||||
} // crashed(Material)
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Determine the center point and radius of a circle given two points on
|
||||
* the circle and the tangent at the first point. This is done as follows:
|
||||
* 1. Determine the line going through the center point start+end, which is
|
||||
* orthogonal to the vector from start to end. This line goes through the
|
||||
* center of the circle.
|
||||
* 2. Determine the line going through the first point and is orthogonal
|
||||
* to the given tangent.
|
||||
* 3. The intersection of these two lines is the center of the circle.
|
||||
* \param[in] end Second point on circle.
|
||||
* \param[out] center Center point of the circle (local coordinate).
|
||||
* \param[out] radius Radius of the circle.
|
||||
*/
|
||||
void AIBaseController::determineTurnRadius(const Vec3 &end, Vec3 *center,
|
||||
float *radius) const
|
||||
{
|
||||
// Convert end point to local coordinate, so start will be 0, 0, 0
|
||||
Vec3 lc = m_kart->getTrans().inverse()(end);
|
||||
|
||||
// 1) Line through middle of start+end
|
||||
Vec3 mid = 0.5f * lc;
|
||||
Vec3 direction = lc;
|
||||
|
||||
Vec3 orthogonal(direction.getZ(), 0, -direction.getX());
|
||||
Vec3 q1 = mid + orthogonal;
|
||||
irr::core::line2df line1(mid.getX(), mid.getZ(),
|
||||
q1.getX(), q1.getZ() );
|
||||
|
||||
irr::core::line2df line2(0, 0, 1, 0);
|
||||
irr::core::vector2df result;
|
||||
if (line1.intersectWith(line2, result, /*checkOnlySegments*/false))
|
||||
{
|
||||
Vec3 lc_center(result.X, 0, result.Y);
|
||||
if (center)
|
||||
*center = lc_center;
|
||||
*radius = lc_center.length();
|
||||
}
|
||||
else
|
||||
{
|
||||
// No intersection. In this case assume that the two points are
|
||||
// on a semicircle, in which case the center is at 0.5*(start+end):
|
||||
if (center)
|
||||
*center = mid;
|
||||
*radius = 0.5f*(lc).length();
|
||||
}
|
||||
|
||||
} // determineTurnRadius
|
||||
|
@ -67,13 +67,15 @@ protected:
|
||||
void setControllerName(const std::string &name);
|
||||
float steerToPoint(const Vec3 &point);
|
||||
float normalizeAngle(float angle);
|
||||
virtual void update (float delta);
|
||||
virtual void setSteering (float angle, float dt);
|
||||
virtual bool canSkid(float steer_fraction) = 0;
|
||||
// ------------------------------------------------------------------------
|
||||
/** 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; }
|
||||
void determineTurnRadius(const Vec3 &end, Vec3 *center,
|
||||
float *radius) const;
|
||||
virtual void update (float delta);
|
||||
virtual void setSteering (float angle, float dt);
|
||||
virtual bool canSkid(float steer_fraction) = 0;
|
||||
|
||||
public:
|
||||
AIBaseController(AbstractKart *kart);
|
||||
|
@ -62,11 +62,8 @@ void ArenaAI::reset()
|
||||
m_time_since_reversing = 0.0f;
|
||||
m_time_since_uturn = 0.0f;
|
||||
m_turn_radius = 0.0f;
|
||||
m_turn_angle = 0.0f;
|
||||
m_steering_angle = 0.0f;
|
||||
m_on_node.clear();
|
||||
m_aiming_points.clear();
|
||||
m_aiming_nodes.clear();
|
||||
|
||||
m_cur_difficulty = race_manager->getDifficulty();
|
||||
AIBaseController::reset();
|
||||
@ -116,7 +113,7 @@ void ArenaAI::update(float dt)
|
||||
}
|
||||
|
||||
checkIfStuck(dt);
|
||||
if (handleArenaUnstuck(dt))
|
||||
if (gettingUnstuck(dt))
|
||||
return;
|
||||
|
||||
findClosestKart(true);
|
||||
@ -126,24 +123,25 @@ void ArenaAI::update(float dt)
|
||||
// u-turn
|
||||
m_target_point_lc = m_kart->getTrans().inverse()(m_target_point);
|
||||
doSkiddingTest();
|
||||
handleArenaItems(dt);
|
||||
configSteering();
|
||||
useItems(dt);
|
||||
|
||||
if (m_kart->getSpeed() > 15.0f && m_turn_angle < 20)
|
||||
if (m_kart->getSpeed() > 15.0f && !m_is_uturn && m_turn_radius > 30.0f &&
|
||||
!ignorePathFinding())
|
||||
{
|
||||
// Only use nitro when turn angle is big (180 - angle)
|
||||
// Only use nitro when turn radius is large
|
||||
m_controls->m_nitro = true;
|
||||
}
|
||||
|
||||
if (m_is_uturn)
|
||||
{
|
||||
resetAfterStop();
|
||||
handleArenaUTurn(dt);
|
||||
doUTurn(dt);
|
||||
}
|
||||
else
|
||||
{
|
||||
handleArenaAcceleration(dt);
|
||||
handleArenaSteering(dt);
|
||||
handleArenaBraking();
|
||||
configSpeed();
|
||||
setSteering(m_steering_angle, dt);
|
||||
}
|
||||
|
||||
AIBaseController::update(dt);
|
||||
@ -151,8 +149,17 @@ void ArenaAI::update(float dt)
|
||||
} // update
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool ArenaAI::updateAimingPosition()
|
||||
/** Update aiming position, use path finding if necessary, it will set the turn
|
||||
* radius too.
|
||||
* \param[out] suitable target point.
|
||||
* \return true if found a suitable target point.
|
||||
*/
|
||||
bool ArenaAI::updateAimingPosition(Vec3* target_point)
|
||||
{
|
||||
#ifdef AI_DEBUG
|
||||
m_debug_sphere_next->setVisible(false);
|
||||
#endif
|
||||
|
||||
// Notice: we use the point ahead of kart to determine next node,
|
||||
// to compensate the time difference between steering
|
||||
m_current_forward_point =
|
||||
@ -168,49 +175,88 @@ bool ArenaAI::updateAimingPosition()
|
||||
test_nodes);
|
||||
|
||||
// Use current node if forward node is unknown, or near the target
|
||||
const int forward = (m_current_forward_node == Graph::UNKNOWN_SECTOR ||
|
||||
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);
|
||||
getCurrentNode() == m_target_node ?
|
||||
getCurrentNode() : m_current_forward_node;
|
||||
|
||||
if (forward == Graph::UNKNOWN_SECTOR ||
|
||||
m_target_node == Graph::UNKNOWN_SECTOR)
|
||||
{
|
||||
Log::error("ArenaAI", "Next node is unknown, path finding failed!");
|
||||
m_turn_radius = 0.0f;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (forward == m_target_node)
|
||||
{
|
||||
m_aiming_points.push_back(m_graph->getNode(forward)->getCenter());
|
||||
m_aiming_points.push_back(m_target_point);
|
||||
if (checkBadItem(&m_target_node))
|
||||
m_target_point = m_graph->getNode(m_target_node)->getCenter();
|
||||
|
||||
m_aiming_nodes.insert(forward);
|
||||
m_aiming_nodes.insert(getCurrentNode());
|
||||
determineTurnRadius(m_target_point, NULL, &m_turn_radius);
|
||||
*target_point = m_target_point;
|
||||
return true;
|
||||
}
|
||||
|
||||
const int next_node = m_graph->getNextNode(forward, m_target_node);
|
||||
int next_node = m_graph->getNextNode(forward, m_target_node);
|
||||
// Use this next node for aim point if valid
|
||||
if (next_node == Graph::UNKNOWN_SECTOR)
|
||||
{
|
||||
Log::error("ArenaAI", "Next node is unknown, did you forget to link"
|
||||
"adjacent face in navmesh?");
|
||||
" adjacent face in navmesh?");
|
||||
m_turn_radius = 0.0f;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_aiming_points.push_back(m_graph->getNode(forward)->getCenter());
|
||||
m_aiming_points.push_back(m_graph->getNode(next_node)->getCenter());
|
||||
checkBadItem(&next_node);
|
||||
*target_point = m_graph->getNode(next_node)->getCenter();
|
||||
|
||||
m_aiming_nodes.insert(forward);
|
||||
m_aiming_nodes.insert(next_node);
|
||||
m_aiming_nodes.insert(getCurrentNode());
|
||||
// Then keep getting next node to find the first turning corner which is
|
||||
// used to determine turn radius
|
||||
while (m_target_node != next_node)
|
||||
{
|
||||
int previous_node = next_node;
|
||||
next_node = m_graph->getNextNode(previous_node, 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?");
|
||||
m_turn_radius = 0.0f;
|
||||
return false;
|
||||
}
|
||||
|
||||
const Vec3& p1 = m_kart->getXYZ();
|
||||
const Vec3& p2 = m_graph->getNode(previous_node)->getCenter();
|
||||
const Vec3& p3 = m_graph->getNode(next_node)->getCenter();
|
||||
float edge1 = (p1 - p2).length();
|
||||
float edge2 = (p2 - p3).length();
|
||||
float to_target = (p1 - p3).length();
|
||||
|
||||
if (fabsf(edge1 + edge2 - to_target) > 0.1f)
|
||||
{
|
||||
// Triangle test
|
||||
determineTurnRadius(p3, NULL, &m_turn_radius);
|
||||
#ifdef AI_DEBUG
|
||||
m_debug_sphere_next->setVisible(true);
|
||||
m_debug_sphere_next->setPosition(p3.toIrrVector());
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Target node == next node
|
||||
determineTurnRadius(m_target_point, NULL, &m_turn_radius);
|
||||
return true;
|
||||
|
||||
} // updateAimingPosition
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** This function sets the steering.
|
||||
* \param dt Time step size.
|
||||
/** This function config the steering of AI.
|
||||
*/
|
||||
void ArenaAI::handleArenaSteering(const float dt)
|
||||
void ArenaAI::configSteering()
|
||||
{
|
||||
m_steering_angle = 0.0f;
|
||||
const int current_node = getCurrentNode();
|
||||
|
||||
if (current_node == Graph::UNKNOWN_SECTOR ||
|
||||
@ -219,12 +265,10 @@ void ArenaAI::handleArenaSteering(const float dt)
|
||||
return;
|
||||
}
|
||||
|
||||
m_aiming_points.clear();
|
||||
m_aiming_nodes.clear();
|
||||
const bool found_position = updateAimingPosition();
|
||||
if (ignorePathFinding())
|
||||
{
|
||||
// Steer directly
|
||||
// Steer directly, don't brake
|
||||
m_turn_radius = 100.0f;
|
||||
#ifdef AI_DEBUG
|
||||
m_debug_sphere->setPosition(m_target_point.toIrrVector());
|
||||
#endif
|
||||
@ -237,23 +281,20 @@ void ArenaAI::handleArenaSteering(const float dt)
|
||||
else
|
||||
{
|
||||
m_steering_angle = steerToPoint(m_target_point);
|
||||
setSteering(m_steering_angle, dt);
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (found_position)
|
||||
|
||||
// Otherwise use path finding to get target point
|
||||
Vec3 target_point;
|
||||
const bool found_position = updateAimingPosition(&target_point);
|
||||
if (found_position)
|
||||
{
|
||||
updateBadItemLocation();
|
||||
assert(m_aiming_points.size() == 2);
|
||||
updateTurnRadius(m_kart->getXYZ(), m_aiming_points[0],
|
||||
m_aiming_points[1]);
|
||||
m_target_point = m_aiming_points[1];
|
||||
m_target_point = target_point;
|
||||
m_target_point_lc = m_kart->getTrans().inverse()(m_target_point);
|
||||
#ifdef AI_DEBUG
|
||||
m_debug_sphere->setVisible(true);
|
||||
m_debug_sphere_next->setVisible(true);
|
||||
m_debug_sphere->setPosition(m_aiming_points[0].toIrrVector());
|
||||
m_debug_sphere_next->setPosition(m_aiming_points[1].toIrrVector());
|
||||
m_debug_sphere->setPosition(m_target_point.toIrrVector());
|
||||
#endif
|
||||
if (m_target_point_lc.z() < 0)
|
||||
{
|
||||
@ -263,17 +304,9 @@ void ArenaAI::handleArenaSteering(const float dt)
|
||||
else
|
||||
{
|
||||
m_steering_angle = steerToPoint(m_target_point);
|
||||
setSteering(m_steering_angle, dt);
|
||||
}
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Do nothing (go straight) if no targets found
|
||||
setSteering(0.0f, dt);
|
||||
return;
|
||||
}
|
||||
} // handleSteering
|
||||
} // configSteering
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void ArenaAI::checkIfStuck(const float dt)
|
||||
@ -311,26 +344,36 @@ void ArenaAI::checkIfStuck(const float dt)
|
||||
} // checkIfStuck
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Handles acceleration.
|
||||
* \param dt Time step size.
|
||||
/** Configure a suitable speed depends on current turn radius.
|
||||
*/
|
||||
void ArenaAI::handleArenaAcceleration(const float dt)
|
||||
void ArenaAI::configSpeed()
|
||||
{
|
||||
m_controls->m_accel = 0.0f;
|
||||
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.
|
||||
|
||||
if (m_controls->m_brake)
|
||||
{
|
||||
m_controls->m_accel = 0.0f;
|
||||
return;
|
||||
}
|
||||
|
||||
const float MIN_SPEED = 5.0f;
|
||||
const float handicap =
|
||||
(m_cur_difficulty == RaceManager::DIFFICULTY_EASY ? 0.7f : 1.0f);
|
||||
m_controls->m_accel = stk_config->m_ai_acceleration * handicap;
|
||||
|
||||
} // handleArenaAcceleration
|
||||
const float max_turn_speed = m_kart->getSpeedForTurnRadius(m_turn_radius);
|
||||
if ((m_kart->getSpeed() > max_turn_speed || forceBraking()) &&
|
||||
m_kart->getSpeed() > MIN_SPEED * handicap)
|
||||
{
|
||||
// Brake if necessary
|
||||
m_controls->m_brake = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise accelerate
|
||||
m_controls->m_accel = stk_config->m_ai_acceleration * handicap;
|
||||
}
|
||||
} // configSpeed
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void ArenaAI::handleArenaUTurn(const float dt)
|
||||
void ArenaAI::doUTurn(const float dt)
|
||||
{
|
||||
const float turn_side = (m_adjusting_side ? 1.0f : -1.0f);
|
||||
|
||||
@ -357,10 +400,10 @@ void ArenaAI::handleArenaUTurn(const float dt)
|
||||
}
|
||||
else
|
||||
m_is_uturn = true;
|
||||
} // handleArenaUTurn
|
||||
} // doUTurn
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool ArenaAI::handleArenaUnstuck(const float dt)
|
||||
bool ArenaAI::gettingUnstuck(const float dt)
|
||||
{
|
||||
if (!m_is_stuck || m_is_uturn) return false;
|
||||
|
||||
@ -384,138 +427,41 @@ bool ArenaAI::handleArenaUnstuck(const float dt)
|
||||
AIBaseController::update(dt);
|
||||
return true;
|
||||
|
||||
} // handleArenaUnstuck
|
||||
} // gettingUnstuck
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void ArenaAI::updateBadItemLocation()
|
||||
bool ArenaAI::checkBadItem(int* node)
|
||||
{
|
||||
// Check if any nodes AI will cross will meet bad items
|
||||
for (const int& node : m_aiming_nodes)
|
||||
// Check if the node AI will cross will meet bad items
|
||||
assert(*node != Graph::UNKNOWN_SECTOR);
|
||||
Item* selected = ItemManager::get()->getFirstItemInQuad(*node);
|
||||
|
||||
if (selected && !selected->wasCollected() &&
|
||||
(selected->getType() == Item::ITEM_BANANA ||
|
||||
selected->getType() == Item::ITEM_BUBBLEGUM ||
|
||||
selected->getType() == Item::ITEM_BUBBLEGUM_NOLOK))
|
||||
{
|
||||
assert(node != Graph::UNKNOWN_SECTOR);
|
||||
Item* selected = ItemManager::get()->getFirstItemInQuad(node);
|
||||
|
||||
if (selected && !selected->wasCollected() &&
|
||||
(selected->getType() == Item::ITEM_BANANA ||
|
||||
selected->getType() == Item::ITEM_BUBBLEGUM ||
|
||||
selected->getType() == Item::ITEM_BUBBLEGUM_NOLOK))
|
||||
// Choose any nearby node that is in front of the AI to prevent hitting
|
||||
// bad item
|
||||
ArenaNode* cur_node = m_graph->getNode(*node);
|
||||
const float dist = (m_kart->getXYZ() - cur_node->getCenter()).length();
|
||||
const std::vector<int>* nearby_nodes = cur_node->getNearbyNodes();
|
||||
for (const int& nearby_node : *nearby_nodes)
|
||||
{
|
||||
Vec3 bad_item_lc =
|
||||
m_kart->getTrans().inverse()(selected->getXYZ());
|
||||
|
||||
// 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)
|
||||
Vec3 lc = m_kart->getTrans().inverse()
|
||||
(m_graph->getNode(nearby_node)->getCenter());
|
||||
if (lc.z() > 0 && dist > lc.length())
|
||||
{
|
||||
continue;
|
||||
*node = nearby_node;
|
||||
return 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;
|
||||
}
|
||||
}
|
||||
|
||||
} // updateBadItemLocation
|
||||
return false;
|
||||
} // checkBadItem
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** This function handles braking. It used the turn radius found by
|
||||
* updateTurnRadius(). Depending on the turn radius, it finds out the maximum
|
||||
* speed. If the current speed is greater than the max speed and a set minimum
|
||||
* speed, brakes are applied.
|
||||
*/
|
||||
void ArenaAI::handleArenaBraking()
|
||||
{
|
||||
// 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.
|
||||
const float MIN_SPEED = 5.0f;
|
||||
|
||||
if (forceBraking() && m_kart->getSpeed() > MIN_SPEED)
|
||||
{
|
||||
// Brake now
|
||||
m_controls->m_brake = true;
|
||||
return;
|
||||
}
|
||||
|
||||
m_controls->m_brake = false;
|
||||
|
||||
if (getCurrentNode() == Graph::UNKNOWN_SECTOR ||
|
||||
m_target_node == Graph::UNKNOWN_SECTOR) return;
|
||||
|
||||
if (m_aiming_points.empty()) return;
|
||||
|
||||
const float max_turn_speed = m_kart->getSpeedForTurnRadius(m_turn_radius);
|
||||
|
||||
if (m_kart->getSpeed() > 1.25f * max_turn_speed &&
|
||||
fabsf(m_controls->m_steer) > 0.95f &&
|
||||
m_kart->getSpeed() > MIN_SPEED)
|
||||
{
|
||||
m_controls->m_brake = true;
|
||||
}
|
||||
|
||||
} // handleArenaBraking
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void ArenaAI::updateTurnRadius(const Vec3& p1, const Vec3& p2,
|
||||
const Vec3& p3)
|
||||
{
|
||||
// First use cosine formula to find out the angle made by the distance
|
||||
// between kart (point one) to point two and point two between point three
|
||||
const float a = (p1 - p2).length();
|
||||
const float b = (p2 - p3).length();
|
||||
const float c = (p1 - p3).length();
|
||||
const float angle = 180 - findAngleFrom3Edges(a, b, c);
|
||||
|
||||
// Only calculate radius if not almost straight line
|
||||
if (angle > 1 && angle < 179)
|
||||
{
|
||||
// angle
|
||||
// ^
|
||||
// a / \ b
|
||||
// 90/\ /\90
|
||||
// \ / \ /
|
||||
// \ /
|
||||
// \ /
|
||||
// \ /
|
||||
// |
|
||||
// Try to estimate the turn radius with the help of a kite-like
|
||||
// polygon as shown, find out the lowest angle which is
|
||||
// (4 - 2) * 180 - 90 - 90 - angle (180 - angle from above)
|
||||
// Then we use this value as the angle of a sector of circle,
|
||||
// a + b as the arc length, then the radius can be calculated easily
|
||||
m_turn_radius = ((a + b) / (angle / 360)) / M_PI / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Return large radius so no braking is needed otherwise
|
||||
m_turn_radius = 45.0f;
|
||||
}
|
||||
m_turn_angle = angle;
|
||||
|
||||
} // updateTurnRadius
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
float ArenaAI::findAngleFrom3Edges(float a, float b, float c)
|
||||
{
|
||||
// Cosine forumla : c2 = a2 + b2 - 2ab cos C
|
||||
float test_value = ((c * c) - (a * a) - (b * b)) / (-(2 * a * b));
|
||||
// Prevent error
|
||||
if (test_value < -1)
|
||||
test_value = -1;
|
||||
else if (test_value > 1)
|
||||
test_value = 1;
|
||||
|
||||
return acosf(test_value) * RAD_TO_DEGREE;
|
||||
|
||||
} // findAngleFrom3Edges
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void ArenaAI::handleArenaItems(const float dt)
|
||||
void ArenaAI::useItems(const float dt)
|
||||
{
|
||||
m_controls->m_fire = false;
|
||||
if (m_kart->getKartAnimation() ||
|
||||
@ -675,7 +621,7 @@ void ArenaAI::handleArenaItems(const float dt)
|
||||
}
|
||||
if (m_controls->m_fire)
|
||||
m_time_since_last_shot = 0.0f;
|
||||
} // handleArenaItems
|
||||
} // useItems
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void ArenaAI::collectItemInArena(Vec3* aim_point, int* target_node) const
|
||||
|
@ -103,28 +103,22 @@ private:
|
||||
float m_time_since_off_road;
|
||||
|
||||
float m_turn_radius;
|
||||
float m_turn_angle;
|
||||
|
||||
float m_steering_angle;
|
||||
|
||||
Vec3 m_current_forward_point;
|
||||
|
||||
int m_current_forward_node;
|
||||
|
||||
std::set<int> m_aiming_nodes;
|
||||
std::vector<Vec3> m_aiming_points;
|
||||
|
||||
void checkIfStuck(const float dt);
|
||||
void doSkiddingTest();
|
||||
float findAngleFrom3Edges(float a, float b, float c);
|
||||
void handleArenaAcceleration(const float dt);
|
||||
void handleArenaBraking();
|
||||
void handleArenaItems(const float dt);
|
||||
void handleArenaSteering(const float dt);
|
||||
void handleArenaUTurn(const float dt);
|
||||
bool handleArenaUnstuck(const float dt);
|
||||
bool updateAimingPosition();
|
||||
void updateBadItemLocation();
|
||||
void updateTurnRadius(const Vec3& p1, const Vec3& p2,
|
||||
const Vec3& p3);
|
||||
void configSpeed();
|
||||
void configSteering();
|
||||
bool checkBadItem(int* node);
|
||||
void checkIfStuck(const float dt);
|
||||
void doSkiddingTest();
|
||||
void doUTurn(const float dt);
|
||||
bool gettingUnstuck(const float dt);
|
||||
bool updateAimingPosition(Vec3* target_point);
|
||||
void useItems(const float dt);
|
||||
virtual bool canSkid(float steer_fraction) OVERRIDE
|
||||
{ return m_mini_skid; }
|
||||
virtual void findClosestKart(bool use_difficulty) = 0;
|
||||
|
@ -2460,49 +2460,3 @@ void SkiddingAI::setSteering(float angle, float dt)
|
||||
|
||||
|
||||
} // setSteering
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Determine the center point and radius of a circle given two points on
|
||||
* the circle and the tangent at the first point. This is done as follows:
|
||||
* 1. Determine the line going through the center point start+end, which is
|
||||
* orthogonal to the vector from start to end. This line goes through the
|
||||
* center of the circle.
|
||||
* 2. Determine the line going through the first point and is orthogonal
|
||||
* to the given tangent.
|
||||
* 3. The intersection of these two lines is the center of the circle.
|
||||
* \param[in] end Second point on circle.
|
||||
* \param[out] center Center point of the circle (local coordinate).
|
||||
* \param[out] radius Radius of the circle.
|
||||
*/
|
||||
void SkiddingAI::determineTurnRadius(const Vec3 &end, Vec3 *center,
|
||||
float *radius)
|
||||
{
|
||||
// Convert end point to local coordinate, so start will be 0, 0, 0
|
||||
Vec3 lc = m_kart->getTrans().inverse()(end);
|
||||
|
||||
// 1) Line through middle of start+end
|
||||
Vec3 mid = 0.5f * lc;
|
||||
Vec3 direction = lc;
|
||||
|
||||
Vec3 orthogonal(direction.getZ(), 0, -direction.getX());
|
||||
Vec3 q1 = mid + orthogonal;
|
||||
irr::core::line2df line1(mid.getX(), mid.getZ(),
|
||||
q1.getX(), q1.getZ() );
|
||||
|
||||
irr::core::line2df line2(0, 0, 1, 0);
|
||||
irr::core::vector2df result;
|
||||
if(line1.intersectWith(line2, result, /*checkOnlySegments*/false))
|
||||
{
|
||||
Vec3 lc_center(result.X, 0, result.Y);
|
||||
*center = lc_center;
|
||||
*radius = lc_center.length();
|
||||
}
|
||||
else
|
||||
{
|
||||
// No intersection. In this case assume that the two points are
|
||||
// on a semicircle, in which case the center is at 0.5*(start+end):
|
||||
*center = mid;
|
||||
*radius = 0.5f*(lc).length();
|
||||
}
|
||||
return;
|
||||
} // determineTurnRadius
|
||||
|
@ -265,7 +265,6 @@ private:
|
||||
void findNonCrashingPoint(Vec3 *result, int *last_node);
|
||||
|
||||
void determineTrackDirection();
|
||||
void determineTurnRadius(const Vec3 &end, Vec3 *center, float *radius);
|
||||
virtual bool canSkid(float steer_fraction);
|
||||
virtual void setSteering(float angle, float dt);
|
||||
void handleCurve();
|
||||
|
Loading…
Reference in New Issue
Block a user