예제 #1
0
/** Returns information on the parameters needed to hit a target kart moving
 *  at constant velocity and direction for a given speed in the XZ-plane.
 *  \param origin Location of the kart shooting the item.
 *  \param target_kart Which kart to target.
 *  \param item_xz_speed Speed of the item projected in XZ plane.
 *  \param gravity The gravity used for this item.
 *  \param forw_offset How far ahead of the kart the item is shot (so that
 *         the item does not originate inside of the shooting kart.
 *  \param fire_angle Returns the angle to fire the item at.
 *  \param up_velocity Returns the upwards velocity to use for the item.
 */
void Flyable::getLinearKartItemIntersection (const Vec3 &origin,
                                             const AbstractKart *target_kart,
                                             float item_XZ_speed,
                                             float gravity, float forw_offset,
                                             float *fire_angle,
                                             float *up_velocity)
{
    Vec3 relative_target_kart_loc = target_kart->getXYZ() - origin;

    btTransform trans = target_kart->getTrans();
    Vec3 target_direction(trans.getBasis().getColumn(2));

    float dx = relative_target_kart_loc.getX();
    float dy = relative_target_kart_loc.getY();
    float dz = relative_target_kart_loc.getZ();

    float gy = target_direction.getY();

    //Projected onto X-Z plane
    float target_kart_speed = target_direction.length_2d()
                            * target_kart->getSpeed();

    float target_kart_heading = target_kart->getHeading();

    float dist = -(target_kart_speed / item_XZ_speed)
               * (dx * cosf(target_kart_heading) -
                  dz * sinf(target_kart_heading)   );

    float fire_th = (dx*dist - dz * sqrtf(dx*dx + dz*dz - dist*dist))
                  / (dx*dx + dz*dz);
    if(fire_th>1)
        fire_th = 1.0f;
    else if (fire_th<-1.0f)
        fire_th = -1.0f;
    fire_th = (((dist - dx*fire_th) / dz > 0) ? -acosf(fire_th)
                                              :  acosf(fire_th));

    float time = 0.0f;
    float a = item_XZ_speed     * sinf (fire_th)
            + target_kart_speed * sinf (target_kart_heading);
    float b = item_XZ_speed     * cosf (fire_th)
            + target_kart_speed * cosf (target_kart_heading);

    if (fabsf(a) > fabsf(b)) time = fabsf (dx / a);
    else if (b != 0.0f)      time = fabsf(dz / b);

    if (fire_th > M_PI)
        fire_th -= M_PI;
    else
        fire_th += M_PI;

    //createPhysics offset
    assert(sqrt(a*a+b*b)!=0);
    time -= forw_offset / sqrt(a*a+b*b);

    assert(time!=0);
    *fire_angle = fire_th;
    *up_velocity = (0.5f * time * gravity) + (dy / time)
                 + (gy * target_kart->getSpeed());
}   // getLinearKartItemIntersection
예제 #2
0
/** Returns information on the parameters needed to hit a target kart moving
 *  at constant velocity and direction for a given speed in the XZ-plane.
 *  \param origin Location of the kart shooting the item.
 *  \param target_kart Which kart to target.
 *  \param item_xz_speed Speed of the item projected in XZ plane.
 *  \param gravity The gravity used for this item.
 *  \param forw_offset How far ahead of the kart the item is shot (so that
 *         the item does not originate inside of the shooting kart.
 *  \param fire_angle Returns the angle to fire the item at.
 *  \param up_velocity Returns the upwards velocity to use for the item.
 */
void Flyable::getLinearKartItemIntersection (const Vec3 &origin,
                                             const AbstractKart *target_kart,
                                             float item_XZ_speed,
                                             float gravity, float forw_offset,
                                             float *fire_angle,
                                             float *up_velocity)
{
    // Transform the target into the firing kart's frame of reference
    btTransform inv_trans = m_owner->getTrans().inverse();
    
    Vec3 relative_target_kart_loc = inv_trans(target_kart->getXYZ());
    
    // Find the direction target is moving in
    btTransform trans = target_kart->getTrans();
    Vec3 target_direction(trans.getBasis().getColumn(2));

    // Now rotate it to the firing kart's frame of reference
    btQuaternion inv_rotate = inv_trans.getRotation();
    target_direction = 
        target_direction.rotate(inv_rotate.getAxis(), inv_rotate.getAngle());
    
    // Now we try to find the angle to aim at to hit the target. 
    // Warning : Funky math stuff going on below. To understand, see answer by 
    // Jeffrey Hantin here : 
    // http://stackoverflow.com/questions/2248876/2d-game-fire-at-a-moving-target-by-predicting-intersection-of-projectile-and-u
    
    float target_x_speed = target_direction.getX()*target_kart->getSpeed();
    float target_z_speed = target_direction.getZ()*target_kart->getSpeed();
    float target_y_speed = target_direction.getY()*target_kart->getSpeed();

    float a = (target_x_speed*target_x_speed) + (target_z_speed*target_z_speed) -
                (item_XZ_speed*item_XZ_speed);
    float b = 2 * (target_x_speed * (relative_target_kart_loc.getX())
                    + target_z_speed * (relative_target_kart_loc.getZ()));
    float c = relative_target_kart_loc.getX()*relative_target_kart_loc.getX()
                + relative_target_kart_loc.getZ()*relative_target_kart_loc.getZ();
    
    float discriminant = b*b - 4 * a*c;
    if (discriminant < 0) discriminant = 0;

    float t1 = (-b + sqrt(discriminant)) / (2 * a);
    float t2 = (-b - sqrt(discriminant)) / (2 * a);
    float time;
    if (t1 >= 0 && t1<t2) time = t1;
    else time = t2;

    //createPhysics offset
    time -= forw_offset / item_XZ_speed;

    float aimX = time*target_x_speed + relative_target_kart_loc.getX();
    float aimZ = time*target_z_speed + relative_target_kart_loc.getZ();

    assert(time!=0);
    float angle = atan2f(aimX, aimZ);
    
    *fire_angle = angle;

    // Now find the up_velocity. This is an application of newton's equation.
    *up_velocity = (0.5f * time * gravity) + (relative_target_kart_loc.getY() / time)
                 + ( target_y_speed);
}   // getLinearKartItemIntersection