Ejemplo n.º 1
0
/** This is the main entry point for the AI.
 *  It is called once per frame for each AI and determines the behaviour of
 *  the AI, e.g. steering, accelerating/braking, firing.
 */
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;

    // Don't do anything if there is currently a kart animations shown.
    if (m_kart->getKartAnimation())
        return;

    if (isWaiting())
    {
        AIBaseController::update(dt);
        return;
    }

    checkIfStuck(dt);
    if (handleArenaUnstuck(dt))
        return;

    findClosestKart(true);
    findTarget();
    handleArenaItems(dt);
    handleArenaBanana();

    if (m_kart->getSpeed() > 15.0f && m_cur_kart_pos_data.angle < 0.2f)
    {
        // Only use nitro when target is straight
        m_controls->m_nitro = true;
    }

    if (m_is_uturn)
    {
        handleArenaUTurn(dt);
    }
    else
    {
        handleArenaAcceleration(dt);
        handleArenaSteering(dt);
        handleArenaBraking();
    }

    AIBaseController::update(dt);

}   // update
Ejemplo n.º 2
0
/** Find a suitable target to follow, it will first call
 *  \ref SoccerWorld::getBallChaser to check if this AI should go chasing the
 *  ball and try to score, otherwise it will call \ref tryCollectItem if
 *  needed. After that it will call \ref SoccerWorld::getAttacker to see if
 *  this AI should attack the kart in opposite team which is chasing the ball,
 *  if not go for the closest kart found by \ref findClosestKart.
 */
void SoccerAI::findTarget()
{
    findClosestKart(true/*consider_difficulty*/, false/*find_sta*/);
    // Check if this AI kart is the one who will chase the ball
    if (m_world->getBallChaser(m_cur_team) == (signed)m_kart->getWorldKartId())
    {
        m_target_point = determineBallAimingPosition();
        m_target_node  = m_world->getBallNode();
        return;
    }

    // Always reset this flag,
    // in case the ball chaser lost the ball somehow
    m_overtake_ball = false;

    if (m_kart->getPowerup()->getType() == PowerupManager::POWERUP_NOTHING &&
        m_kart->getAttachment()->getType() != Attachment::ATTACH_SWATTER)
    {
        tryCollectItem(&m_target_point , &m_target_node);
    }
    else if (m_world->getAttacker(m_cur_team) == (signed)m_kart
        ->getWorldKartId())
    {
        // This AI will attack the other team ball chaser
        int id = m_world->getBallChaser(m_opp_team);
        const AbstractKart* kart = m_world->getKart(id);
        m_target_point = kart->getXYZ();
        m_target_node  = m_world->getSectorForKart(kart);
    }
    else
    {
        m_target_point = m_closest_kart_point;
        m_target_node  = m_closest_kart_node;
    }

}   // findTarget
Ejemplo n.º 3
0
/** Determine how AI should use its item, different \ref m_cur_difficulty will
 *  have a corresponding strategy.
 *  \param dt Time step size.
 */
void ArenaAI::useItems(const float dt)
{
    m_controls->setFire(false);
    if (m_kart->getKartAnimation() ||
        m_kart->getPowerup()->getType() == PowerupManager::POWERUP_NOTHING)
        return;

    // Find a closest kart again, this time we ignore difficulty
    findClosestKart(false/*consider_difficulty*/, false/*find_sta*/);
    if (!m_closest_kart) return;

    Vec3 closest_kart_point_lc =
        m_kart->getTrans().inverse()(m_closest_kart_point);

    m_time_since_last_shot += dt;

    float min_bubble_time = 2.0f;
    const bool difficulty = m_cur_difficulty == RaceManager::DIFFICULTY_EASY ||
                            m_cur_difficulty == RaceManager::DIFFICULTY_MEDIUM;

    const bool fire_behind = closest_kart_point_lc.z() < 0 && !difficulty;

    const float abs_angle = atan2f(fabsf(closest_kart_point_lc.x()),
        fabsf(closest_kart_point_lc.z()));
    const bool perfect_aim = abs_angle < 0.2f;

    // Compensate the distance because this distance is straight to straight
    // in graph node, so if kart to kart are not facing like so as, their real
    // distance maybe smaller
    const float dist_to_kart = getKartDistance(m_closest_kart) * 0.8f;

    switch(m_kart->getPowerup()->getType())
    {
    case PowerupManager::POWERUP_BUBBLEGUM:
        {
            Attachment::AttachmentType type = m_kart->getAttachment()->getType();
            // Don't use shield when we have a swatter.
            if (type == Attachment::ATTACH_SWATTER)
                break;

            // Check if a flyable (cake, ...) is close or a kart nearby
            // has a swatter attachment. If so, use bubblegum
            // as shield
            if ( (!m_kart->isShielded() &&
                   projectile_manager->projectileIsClose(m_kart,
                                    m_ai_properties->m_shield_incoming_radius)  ) ||
                 (dist_to_kart < 15.0f &&
                  (m_closest_kart->getAttachment()->
                                       getType() == Attachment::ATTACH_SWATTER)  )    )
            {
                m_controls->setFire(true);
                m_controls->setLookBack(false);
                break;
            }

            // Avoid dropping all bubble gums one after another
            if (m_time_since_last_shot < 3.0f) break;

            // Use bubblegum if the kart around is close,
            // or can't find a close kart for too long time
            if (dist_to_kart < 15.0f || m_time_since_last_shot > 15.0f)
            {
                m_controls->setFire(true);
                m_controls->setLookBack(true);
                break;
            }

            break;   // POWERUP_BUBBLEGUM
        }
    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 < 1.0f) break;

            if (dist_to_kart < 25.0f &&
                !m_closest_kart->isInvulnerable())
            {
                m_controls->setFire(true);
                m_controls->setLookBack(fire_behind);
                break;
            }

            break;
        }   // POWERUP_CAKE

    case PowerupManager::POWERUP_BOWLING:
        {
            // if the kart has a shield, do not break it by using a bowling ball.
            if (m_kart->getShieldTime() > min_bubble_time)
                break;

            // Leave some time between shots
            if (m_time_since_last_shot < 1.0f) break;

            if (dist_to_kart < 6.0f &&
                (difficulty || perfect_aim) &&
                !m_closest_kart->isInvulnerable())
            {
                m_controls->setFire(true);
                m_controls->setLookBack(fire_behind);
                break;
            }

            break;
        }   // POWERUP_BOWLING

    case PowerupManager::POWERUP_SWATTER:
        {
            // Squared distance for which the swatter works
            float d2 = m_kart->getKartProperties()->getSwatterDistance();
            // if the kart has a shield, do not break it by using a swatter.
            if (m_kart->getShieldTime() > min_bubble_time)
                break;

            if (!m_closest_kart->isSquashed()          &&
                 dist_to_kart * dist_to_kart < d2 &&
                 m_closest_kart->getSpeed() < m_kart->getSpeed())
            {
                m_controls->setFire(true);
                m_controls->setLookBack(false);
                break;
            }
            break;
        }

    // Below powerups won't appear in arena, so skip them
    case PowerupManager::POWERUP_ZIPPER:
        break;   // POWERUP_ZIPPER

    case PowerupManager::POWERUP_PLUNGER:
        break;   // POWERUP_PLUNGER

    case PowerupManager::POWERUP_SWITCH: // Don't handle switch
        m_controls->setFire(true);       // (use it no matter what) for now
        break;   // POWERUP_SWITCH

    case PowerupManager::POWERUP_PARACHUTE:
        break;   // POWERUP_PARACHUTE

    case PowerupManager::POWERUP_ANVIL:
        break;   // POWERUP_ANVIL

    case PowerupManager::POWERUP_RUBBERBALL:
        break;

    default:
        Log::error("ArenaAI",
                "Invalid or unhandled powerup '%d' in default AI.",
                m_kart->getPowerup()->getType());
        assert(false);
    }
    if (m_controls->getFire())
        m_time_since_last_shot  = 0.0f;
}   // useItems
Ejemplo n.º 4
0
//-----------------------------------------------------------------------------
void ArenaAI::handleArenaItems(const float dt)
{
    m_controls->m_fire = false;
    if (m_kart->getKartAnimation() ||
        m_kart->getPowerup()->getType() == PowerupManager::POWERUP_NOTHING)
        return;

    // Find a closest kart again, this time we ignore difficulty
    findClosestKart(false);

    if (!m_closest_kart) return;

    m_time_since_last_shot += dt;

    float min_bubble_time = 2.0f;
    const bool difficulty = m_cur_difficulty == RaceManager::DIFFICULTY_EASY ||
                            m_cur_difficulty == RaceManager::DIFFICULTY_MEDIUM;

    const bool fire_behind = m_closest_kart_pos_data.behind && !difficulty;

    const bool perfect_aim = m_closest_kart_pos_data.angle < 0.2f;

    switch(m_kart->getPowerup()->getType())
    {
    case PowerupManager::POWERUP_BUBBLEGUM:
        {
            Attachment::AttachmentType type = m_kart->getAttachment()->getType();
            // Don't use shield when we have a swatter.
            if (type == Attachment::ATTACH_SWATTER       ||
                type == Attachment::ATTACH_NOLOKS_SWATTER)
                break;

            // Check if a flyable (cake, ...) is close or a kart nearby
            // has a swatter attachment. If so, use bubblegum
            // as shield
            if ((!m_kart->isShielded() &&
                projectile_manager->projectileIsClose(m_kart,
                                    m_ai_properties->m_shield_incoming_radius)) ||
               (m_closest_kart_pos_data.distance < 15.0f &&
               ((m_closest_kart->getAttachment()->
                getType() == Attachment::ATTACH_SWATTER) ||
               (m_closest_kart->getAttachment()->
                getType() == Attachment::ATTACH_NOLOKS_SWATTER))))
            {
                m_controls->m_fire      = true;
                m_controls->m_look_back = false;
                break;
            }

            // 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,
            // 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;
                break;
            }

            break;   // POWERUP_BUBBLEGUM
        }
    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 < 1.0f) break;

            if (m_closest_kart_pos_data.distance < 25.0f &&
                !m_closest_kart->isInvulnerable())
            {
                m_controls->m_fire      = true;
                m_controls->m_look_back = fire_behind;
                break;
            }

            break;
        }   // POWERUP_CAKE

    case PowerupManager::POWERUP_BOWLING:
        {
            // if the kart has a shield, do not break it by using a bowling ball.
            if (m_kart->getShieldTime() > min_bubble_time)
                break;

            // Leave some time between shots
            if (m_time_since_last_shot < 1.0f) break;

            if (m_closest_kart_pos_data.distance < 6.0f &&
                (difficulty || perfect_aim))
            {
                m_controls->m_fire      = true;
                m_controls->m_look_back = fire_behind;
                break;
            }

            break;
        }   // POWERUP_BOWLING

    case PowerupManager::POWERUP_SWATTER:
        {
            // Squared distance for which the swatter works
            float d2 = m_kart->getKartProperties()->getSwatterDistance();
            // if the kart has a shield, do not break it by using a swatter.
            if (m_kart->getShieldTime() > min_bubble_time)
                break;

            if (!m_closest_kart->isSquashed()          &&
                 m_closest_kart_pos_data.distance < d2 &&
                 m_closest_kart->getSpeed() < m_kart->getSpeed())
            {
                m_controls->m_fire      = true;
                m_controls->m_look_back = false;
                break;
            }
            break;
        }

    // Below powerups won't appear in arena, so skip them
    case PowerupManager::POWERUP_ZIPPER:
        break;   // POWERUP_ZIPPER

    case PowerupManager::POWERUP_PLUNGER:
        break;   // POWERUP_PLUNGER

    case PowerupManager::POWERUP_SWITCH: // Don't handle switch
        m_controls->m_fire = true;       // (use it no matter what) for now
        break;   // POWERUP_SWITCH

    case PowerupManager::POWERUP_PARACHUTE:
        break;   // POWERUP_PARACHUTE

    case PowerupManager::POWERUP_ANVIL:
        break;   // POWERUP_ANVIL

    case PowerupManager::POWERUP_RUBBERBALL:
        break;

    default:
        Log::error("ArenaAI",
                "Invalid or unhandled powerup '%d' in default AI.",
                m_kart->getPowerup()->getType());
        assert(false);
    }
    if (m_controls->m_fire)
        m_time_since_last_shot  = 0.0f;
}   // handleArenaItems