예제 #1
0
/** This function handles braking. It calls determineTurnRadius() to find out
 *  the curve radius. 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()
{
    m_controls->m_brake = false;

    if (getCurrentNode() == BattleGraph::UNKNOWN_POLY ||
        m_target_node    == BattleGraph::UNKNOWN_POLY) return;

    // 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;

    std::vector<Vec3> points;

    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]);

    float current_curve_radius = determineTurnRadius(points);

    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();

    float max_turn_speed = m_kart->getSpeedForTurnRadius(current_curve_radius);

    if (m_kart->getSpeed() > max_turn_speed &&
        m_kart->getSpeed() > MIN_SPEED)
    {
        m_controls->m_brake = true;
    }

}   // handleArenaBraking
예제 #2
0
파일: arena_ai.cpp 프로젝트: Benau/stk-code
/** Determine if the path to target needs to be changed to avoid bad items, it
 *  will also set the turn radius based on the new path if necessary.
 *  \param forward Forward node of current AI position.
 *  \param[in,out] path Default path to follow, will be changed if needed.
 */
void ArenaAI::determinePath(int forward, std::vector<int>* path)
{
    std::vector<int> bad_item_nodes;
    // First, test if the nodes AI will cross contain bad item
    for (unsigned int i = 0; i < path->size(); i++)
    {
        // Only test few nodes ahead
        if (i == 6) break;
        const int node = (*path)[i];
        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))
        {
            bad_item_nodes.push_back(node);
        }
    }

    // If so try to avoid
    if (!bad_item_nodes.empty())
    {
        bool failed_avoid = false;
        for (unsigned int i = 0; i < path->size(); i++)
        {
            if (failed_avoid) break;
            if (i == 6) break;
            // Choose any adjacent node that is in front of the AI to prevent
            // hitting bad item
            ArenaNode* cur_node =
                m_graph->getNode(i == 0 ? forward : (*path)[i - 1]);
            float dist = 99999.9f;
            const std::vector<int>& adj_nodes = cur_node->getAdjacentNodes();
            int chosen_node = Graph::UNKNOWN_SECTOR;
            for (const int& adjacent : adj_nodes)
            {
                if (std::find(bad_item_nodes.begin(), bad_item_nodes.end(),
                    adjacent) != bad_item_nodes.end())
                    continue;

                Vec3 lc = m_kart->getTrans().inverse()
                    (m_graph->getNode(adjacent)->getCenter());
                const float dist_to_target =
                    m_graph->getDistance(adjacent, m_target_node);
                if (lc.z() > 0 && dist > dist_to_target)
                {
                    chosen_node = adjacent;
                    dist = dist_to_target;
                }
                if (chosen_node == Graph::UNKNOWN_SECTOR)
                {
                    Log::debug("ArenaAI", "Too many bad items to avoid!");
                    failed_avoid = true;
                    break;
                }
                (*path)[i] = chosen_node;
            }
        }
    }

    // Now find the first turning corner to determine turn radius
    for (unsigned int i = 0; i < path->size() - 1; i++)
    {
        const Vec3& p1 = m_kart->getXYZ();
        const Vec3& p2 = m_graph->getNode((*path)[i])->getCenter();
        const Vec3& p3 = m_graph->getNode((*path)[i + 1])->getCenter();
        float edge1 = (p1 - p2).length();
        float edge2 = (p2 - p3).length();
        float to_target = (p1 - p3).length();

        // Triangle test
        if (fabsf(edge1 + edge2 - to_target) > 0.1f)
        {
            determineTurnRadius(p3, NULL, &m_turn_radius);
#ifdef AI_DEBUG
            m_debug_sphere_next->setVisible(true);
            m_debug_sphere_next->setPosition(p3.toIrrVector());
#endif
            return;
        }
    }

    // Fallback calculation
    determineTurnRadius(m_target_point, NULL, &m_turn_radius);

}   // determinePath
예제 #3
0
파일: arena_ai.cpp 프로젝트: Benau/stk-code
/** Update aiming position, use path finding if necessary.
 *  \param[out] target_point 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

    m_current_forward_point = m_kart->getTrans()(Vec3(0, 0, m_kart_length));

    m_turn_radius = 0.0f;
    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 == Graph::UNKNOWN_SECTOR ||
        m_current_forward_node == m_target_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!");
        return false;
    }

    if (forward == m_target_node)
    {
        determineTurnRadius(m_target_point, NULL, &m_turn_radius);
        *target_point = m_target_point;
        return true;
    }

    std::vector<int> path;
    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;
    }

    path.push_back(next_node);
    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?");
            return false;
        }
        path.push_back(next_node);
    }

    determinePath(forward, &path);
    *target_point = m_graph->getNode(path.front())->getCenter();

    return true;

}   // updateAimingPosition