Ejemplo n.º 1
0
// -----------------------------------------------------------------------------
void Plunger::update(float dt)
{
    // In keep-alive mode, just update the rubber band
    if(m_keep_alive >= 0)
    {
        m_keep_alive -= dt;
        if(m_keep_alive<=0)
        {
            setHasHit();
            projectile_manager->notifyRemove();
        }
        if(m_rubber_band != NULL) m_rubber_band->update(dt);
        return;
    }

    // Else: update the flyable and rubber band
    Flyable::update(dt);
    if(m_rubber_band != NULL) m_rubber_band->update(dt);

    if(getHoT()==Track::NOHIT) return;
}   // update
Ejemplo n.º 2
0
/** Updates the bowling ball ineach frame. If this function returns true, the
 *  object will be removed by the projectile manager.
 *  \param dt Time step size.
 *  \returns True of this object should be removed.
 */
bool Bowling::updateAndDelete(float dt)
{
    bool can_be_deleted = Flyable::updateAndDelete(dt);
    if(can_be_deleted)
        return true;

    const AbstractKart *kart=0;
    Vec3        direction;
    float       minDistance;
    getClosestKart(&kart, &minDistance, &direction);
    if(kart && minDistance<m_st_max_distance_squared)   // move bowling towards kart
    {
        // limit angle, so that the bowling ball does not turn
        // around to hit a kart behind
        if(fabs(m_body->getLinearVelocity().angle(direction)) < 1.3)
        {
            direction*=1/direction.length()*m_st_force_to_target;
            m_body->applyCentralForce(direction);
        }
    }

    // Bowling balls lose energy (e.g. when hitting the track), so increase
    // the speed if the ball is too slow, but only if it's not too high (if
    // the ball is too high, it is 'pushed down', which can reduce the
    // speed, which causes the speed to increase, which in turn causes
    // the ball to fly higher and higher.
    //btTransform trans = getTrans();
    float hat         = getXYZ().getY()-getHoT();
    if(hat-0.5f*m_extend.getY()<0.01f)
    {
        const Material *material = getMaterial();
        if(!material || material->isDriveReset())
        {
            hit(NULL);
            return true;
        }
    }
    btVector3 v       = m_body->getLinearVelocity();
    float vlen        = v.length2();
    if (hat<= m_max_height)
    {
        if(vlen<0.8*m_speed*m_speed)
        {   // bowling lost energy (less than 80%), i.e. it's too slow - speed it up:
            if(vlen==0.0f) {
                v = btVector3(.5f, .0, 0.5f);  // avoid 0 div.
            }
 //           m_body->setLinearVelocity(v*(m_speed/sqrt(vlen)));
        }   // vlen < 0.8*m_speed*m_speed
    }   // hat< m_max_height

    if(vlen<0.1)
    {
        hit(NULL);
        return true;
    }

    if (m_roll_sfx->getStatus()==SFXBase::SFX_PLAYING)
        m_roll_sfx->setPosition(getXYZ());

    return false;
}   // updateAndDelete
/** Updates the rubber ball.
 *  \param dt Time step size.
 *  \returns True if the rubber ball should be removed.
 */
bool RubberBall::updateAndDelete(float dt)
{
    LinearWorld *world = dynamic_cast<LinearWorld*>(World::getWorld());
    // FIXME: what does the rubber ball do in case of battle mode??
    if(!world) return true;

    if(m_delete_timer>0)
    {
        m_delete_timer -= dt;
        if(m_delete_timer<=0)
        {
            hit(NULL);
#ifdef PRINT_BALL_REMOVE_INFO
            Log::debug("RubberBall", "ball %d deleted.", m_id);
#endif
            return true;
        }
    }

    // Update the target in case that the first kart was overtaken (or has
    // finished the race).
    computeTarget();
    updateDistanceToTarget();

    // Determine the new position. This new position is only temporary,
    // since it still needs to be adjusted for the height of the terrain.
    Vec3 next_xyz;
    if(m_aiming_at_target)
        moveTowardsTarget(&next_xyz, dt);
    else
        interpolate(&next_xyz, dt);

    // If the ball is close to the ground, we have to start the raycast
    // slightly higher (to avoid that the ball tunnels through the floor).
    // But if the ball is close to the ceiling of a tunnel and we would
    // start the raycast slightly higher, the ball might end up on top
    // of the ceiling.
    // The ball is considered close to the ground if the height above the
    // terrain is less than half the current maximum height.
    bool close_to_ground = 2.0*m_previous_height < m_current_max_height;

    float vertical_offset = close_to_ground ? 4.0f : 2.0f;
    // Note that at this stage getHoT still reports the height at
    // the previous location (since TerrainInfo wasn't updated). On
    // the other hand, we can't update TerrainInfo without having
    // at least a good estimation of the height.
    next_xyz.setY(getHoT() + vertical_offset);
    // Update height of terrain (which isn't done as part of
    // Flyable::update for rubber balls.
    TerrainInfo::update(next_xyz);

    m_height_timer += dt;
    float height    = updateHeight()+m_extend.getY()*0.5f;
    float new_y     = getHoT()+height;

    if(UserConfigParams::logFlyable())
        printf("ball %d: %f %f %f height %f new_y %f gethot %f ",
                m_id, next_xyz.getX(), next_xyz.getY(), next_xyz.getZ(), height, new_y, getHoT());

    // No need to check for terrain height if the ball is low to the ground
    if(height > 0.5f)
    {
        float terrain_height = getMaxTerrainHeight(vertical_offset)
                             - m_extend.getY();
        if(new_y>terrain_height)
            new_y = terrain_height;
    }

    if(UserConfigParams::logFlyable())
        Log::verbose("RubberBall", "newy2 %f gmth %f", new_y,
                     getMaxTerrainHeight(vertical_offset));

    next_xyz.setY(new_y);
    m_previous_xyz = getXYZ();
    m_previous_height = next_xyz.getY()-getHoT();
    setXYZ(next_xyz);

    if(checkTunneling())
        return true;

    // Determine new distance along track
    TrackSector::update(next_xyz);

    // Ball squashing:
    // ===============
    if(height<1.5f*m_extend.getY())
        m_node->setScale(core::vector3df(1.0f, height/m_extend.getY(),1.0f));
    else
        m_node->setScale(core::vector3df(1.0f, 1.0f, 1.0f));

    return Flyable::updateAndDelete(dt);
}   // updateAndDelete
Ejemplo n.º 4
0
/** Updates this flyable. It calls Moveable::update. If this function returns
 *  true, the flyable will be deleted by the projectile manager.
 *  \param dt Time step size.
 *  \returns True if this object can be deleted.
 */
bool Flyable::updateAndDelete(float dt)
{
    m_time_since_thrown += dt;
    if(m_max_lifespan > -1 && m_time_since_thrown > m_max_lifespan)
        hit(NULL);

    if(m_has_hit_something) return true;

    //Vec3 xyz=getBody()->getWorldTransform().getOrigin();
    const Vec3 &xyz=getXYZ();
    // Check if the flyable is outside of the track. If so, explode it.
    const Vec3 *min, *max;
    World::getWorld()->getTrack()->getAABB(&min, &max);

    // I have seen that the bullet AABB can be slightly different from the
    // one computed here - I assume due to minor floating point errors
    // (e.g. 308.25842 instead of 308.25845). To avoid a crash with a bullet
    // assertion (see bug 3058932) I add an epsilon here - but admittedly
    // that does not really explain the bullet crash, since bullet tests
    // against its own AABB, and should therefore not cause the assertion.
    // But since we couldn't reproduce the problem, and the epsilon used
    // here does not hurt, I'll leave it in.
    float eps = 0.1f;
    assert(!isnan(xyz.getX()));
    assert(!isnan(xyz.getY()));
    assert(!isnan(xyz.getZ()));
    if(xyz[0]<(*min)[0]+eps || xyz[2]<(*min)[2]+eps || xyz[1]<(*min)[1]+eps ||
       xyz[0]>(*max)[0]-eps || xyz[2]>(*max)[2]-eps || xyz[1]>(*max)[1]-eps   )
    {
        hit(NULL);    // flyable out of track boundary
        return true;
    }

    // Add the position offset so that the flyable can adjust its position
    // (usually to do the raycast from a slightly higher position to avoid
    // problems finding the terrain in steep uphill sections).
    if(m_do_terrain_info)
        TerrainInfo::update(xyz+m_position_offset);

    if(m_adjust_up_velocity)
    {
        float hat = xyz.getY()-getHoT();

        // Use the Height Above Terrain to set the Z velocity.
        // HAT is clamped by min/max height. This might be somewhat
        // unphysical, but feels right in the game.

        float delta = m_average_height - std::max(std::min(hat, m_max_height),
                                                  m_min_height);
        Vec3 v = getVelocity();
        assert(!isnan(v.getX()));
        assert(!isnan(v.getX()));
        assert(!isnan(v.getX()));
        float heading = atan2f(v.getX(), v.getZ());
        assert(!isnan(heading));
        float pitch   = getTerrainPitch(heading);
        float vel_up = m_force_updown*(delta);
        if (hat < m_max_height) // take into account pitch of surface
            vel_up += v.length_2d()*tanf(pitch);
        assert(!isnan(vel_up));
        v.setY(vel_up);
        setVelocity(v);
    }   // if m_adjust_up_velocity

    Moveable::update(dt);

    return false;
}   // updateAndDelete