Applied cake improvements patch by David (thanks\!)

git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/irrlicht@3758 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
auria
2009-07-18 00:02:16 +00:00
parent 75d301417c
commit b6c5f07471
4 changed files with 134 additions and 53 deletions

View File

@@ -3,6 +3,9 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2007 Joerg Henrichs
//
// Physics improvements and linear intersection algorithm by
// by David Mikos. Copyright (C) 2009.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
@@ -26,64 +29,70 @@
float Cake::m_st_max_distance;
float Cake::m_st_max_distance_squared;
float Cake::m_gravity;
Cake::Cake (Kart *kart) : Flyable(kart, POWERUP_CAKE)
{
m_target = NULL;
// A bit of a hack: the mass of this kinematic object is still 1.0
// (see flyable), which enables collisions. I tried setting
// collisionFilterGroup/mask, but still couldn't get this object to
// A bit of a hack: the mass of this kinematic object is still 1.0
// (see flyable), which enables collisions. I tried setting
// collisionFilterGroup/mask, but still couldn't get this object to
// collide with the track. By setting the mass to 1, collisions happen.
// (if bullet is compiled with _DEBUG, a warning will be printed the first
// time a homing-track collision happens).
float y_offset=kart->getKartLength()/2.0f + m_extend.getY()/2.0f;
float up_velocity = m_speed/7.0f;
// give a speed proportinal to kart speed
m_speed = 25.0f + kart->getSpeed()/25.0f * m_speed;
// give a speed proportional to kart speed
m_speed = kart->getSpeed() * m_speed / 23.0f;
if (kart->getSpeed() < 0)
m_speed /= 3.5f; //when going backwards, decrease speed of cake by less
m_speed += 16.0f;
if (m_speed < 1.0f)
m_speed = 1.0f;
btTransform trans = kart->getTrans();
const float pitch = 0.0f; //getTerrainPitch(heading); TODO: take pitch in account
btMatrix3x3 thisKartDirMatrix = kart->getKartHeading().getBasis();
btVector3 thisKartDirVector(thisKartDirMatrix[0][1],
thisKartDirMatrix[1][1],
thisKartDirMatrix[2][1]);
float heading=atan2f(-thisKartDirVector.getX(), thisKartDirVector.getY());
float pitch = kart->getTerrainPitch(heading);
// find closest kart in front of the current one
const Kart *closest_kart=0; btVector3 direction; float kartDistSquared;
getClosestKart(&closest_kart, &kartDistSquared, &direction, kart /* search in front of this kart */);
// aim at this kart if 1) it's not too far, 2) if the aimed kart's speed
// allows the projectile to catch up with it
//
// this code finds the correct angle and upwards velocity to hit an opponents'
// vehicle if they were to continue travelling in the same direction and same speed
// (barring any obstacles in the way of course)
if(closest_kart != NULL && kartDistSquared < m_st_max_distance_squared && m_speed>closest_kart->getSpeed())
{
m_target = (Kart*)closest_kart;
// calculate appropriate initial up velocity so that the
// projectile lands on the aimed kart (9.8 is the gravity)
// FIXME - this approximation will be wrong if both karts' directions are not colinear
// FIXME - this approximation will be wrong if both karts' directions are not at the same height
const float time = sqrt(kartDistSquared) / (m_speed - closest_kart->getSpeed()/1.2f); // division is an empirical estimation
up_velocity = time*9.8f;
// calculate the approximate location of the aimed kart in 'time' seconds
btVector3 closestKartLoc = closest_kart->getTrans().getOrigin();
closestKartLoc += time*closest_kart->getVelocity();
// calculate the angle at which the projectile should be thrown
// to hit the aimed kart
float projectileAngle=atan2(-(closestKartLoc.getX() - kart->getTrans().getOrigin().getX()),
closestKartLoc.getY() - kart->getTrans().getOrigin().getY() );
float fire_angle = 0.0f;
float time_estimated = 0.0f;
getLinearKartItemIntersection (kart->getTrans().getOrigin(), closest_kart,
m_speed, m_gravity,
&fire_angle, &up_velocity, &time_estimated);
btMatrix3x3 thisKartDirMatrix = kart->getKartHeading().getBasis();
btVector3 thisKartDirVector(thisKartDirMatrix[0][1],
thisKartDirMatrix[1][1],
thisKartDirMatrix[2][1]);
// apply transformation to the bullet object
// apply transformation to the bullet object (without pitch)
btMatrix3x3 m;
m.setEulerZYX(pitch, 0.0f, projectileAngle /*+thisKartAngle*/);
m.setEulerZYX(0.0f, 0.0f, fire_angle /*+thisKartAngle*/);
trans.setBasis(m);
}
else
{
@@ -92,18 +101,17 @@ Cake::Cake (Kart *kart) : Flyable(kart, POWERUP_CAKE)
// straight ahead, without trying to hit anything in particular
trans = kart->getKartHeading(pitch);
}
m_initial_velocity = btVector3(0.0f, m_speed, up_velocity);
createPhysics(y_offset, m_initial_velocity,
new btCylinderShape(0.5f*m_extend), -9.8f /* gravity */,
createPhysics(y_offset, m_initial_velocity,
new btCylinderShape(0.5f*m_extend), -m_gravity,
true /* rotation */, false /* backwards */, &trans);
m_body->setActivationState(DISABLE_DEACTIVATION);
m_body->applyTorque( btVector3(5,-3,7) );
} // Cake
// -----------------------------------------------------------------------------
@@ -112,7 +120,12 @@ void Cake::init(const lisp::Lisp* lisp, scene::IMesh *cake_model)
Flyable::init(lisp, cake_model, POWERUP_CAKE);
m_st_max_distance = 80.0f;
m_st_max_distance_squared = 80.0f * 80.0f;
m_gravity = 9.8f;
if (m_gravity < 0)
m_gravity *= -1;
lisp->get("max-distance", m_st_max_distance );
m_st_max_distance_squared = m_st_max_distance*m_st_max_distance;
} // init
@@ -120,27 +133,26 @@ void Cake::init(const lisp::Lisp* lisp, scene::IMesh *cake_model)
// -----------------------------------------------------------------------------
void Cake::update(float dt)
{
if(m_target != NULL)
{
/*
// correct direction to go towards aimed kart
btTransform my_trans = getTrans();
btTransform target = m_target->getTrans();
btVector3 ideal_direction = target.getOrigin() - my_trans.getOrigin();
ideal_direction.normalize();
const btVector3& actual_direction = m_body -> getLinearVelocity();
ideal_direction.setInterpolate3(actual_direction.normalized(), ideal_direction, dt);
const float current_xy_speed = sqrt( actual_direction.getX()*actual_direction.getX() +
actual_direction.getY()*actual_direction.getY());
m_body->setLinearVelocity( btVector3(ideal_direction.getX()*current_xy_speed,
ideal_direction.getY()*current_xy_speed,
actual_direction.getZ()) );
float fire_angle = 0.0f;
float time_estimated = 0.0f;
float up_velocity = 0.0f;
getLinearKartItemIntersection (my_trans.getOrigin(), m_target,
m_speed, m_gravity,
&fire_angle, &up_velocity, &time_estimated);
m_body->setLinearVelocity( btVector3(-m_speed * sinf (fire_angle),
m_speed * cosf (fire_angle),
up_velocity) );
*/
/*
// pull towards aimed kart
btVector3 pullForce = target.getOrigin() - my_trans.getOrigin();
@@ -158,6 +170,7 @@ void Cake::update(float dt)
}
*/
}
Flyable::update(dt);
} // update

View File

@@ -3,6 +3,9 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2007 Joerg Henrichs
//
// Physics improvements and linear intersection algorithm by
// by David Mikos. Copyright (C) 2009.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
@@ -30,6 +33,7 @@ class Cake : public Flyable
private:
static float m_st_max_distance; // maximum distance for a missile to be attracted
static float m_st_max_distance_squared;
static float m_gravity;
btVector3 m_initial_velocity;
Kart* m_target; // which kart is targeted by this

View File

@@ -3,6 +3,9 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2007 Joerg Henrichs
//
// Linear item-kart intersection function written by
// by David Mikos. Copyright (C) 2009.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
@@ -184,6 +187,54 @@ void Flyable::getClosestKart(const Kart **minKart, float *minDistSquared,
} // getClosestKart
//-----------------------------------------------------------------------------
void Flyable::getLinearKartItemIntersection (const btVector3 origin, const Kart *target_kart,
float item_XY_speed, float gravity,
float *fire_angle, float *up_velocity, float *time_estimated)
{
btVector3 targetKartLoc = target_kart->getTrans().getOrigin();
float dx = targetKartLoc.getX() - origin.getX();
float dy = targetKartLoc.getY() - origin.getY();
float dz = targetKartLoc.getZ() - origin.getZ();
btTransform trans = target_kart->getTrans();
btVector3 target_direction(trans.getBasis()[0][1],
trans.getBasis()[1][1],
trans.getBasis()[2][1]);
float gx = target_direction.getX();
float gy = target_direction.getY();
float gz = target_direction.getZ();
float target_kart_speed = hypotf(gx, gy) * target_kart->getSpeed(); //Projected onto X-Y plane
float target_kart_heading = atan2f(-gx, gy); //anti-clockwise
target_kart_heading += M_PI;
float dist = (target_kart_speed / item_XY_speed) * (dx * cosf(target_kart_heading) + dy * sinf(target_kart_heading));
float fire_th = (dx*dist - dy * sqrtf(dx*dx + dy*dy - dist*dist)) / (dx*dx + dy*dy);
fire_th = (((dist - dx*fire_th) / dy < 0) ? -acosf(fire_th): acosf(fire_th));
float time = 0.0f;
float a = item_XY_speed * sinf (fire_th) - target_kart_speed * sinf (target_kart_heading);
float b = item_XY_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(dy / b);
fire_th += M_PI;
*fire_angle = fire_th;
*up_velocity = (0.5 * time * gravity) + (dz / time) + (gz * target_kart->getSpeed());
*time_estimated = time;
}
//-----------------------------------------------------------------------------
void Flyable::update(float dt)
{

View File

@@ -3,6 +3,9 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2007 Joerg Henrichs
//
// Linear item-kart intersection function written by
// by David Mikos. Copyright (C) 2009.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
@@ -87,6 +90,16 @@ protected:
void getClosestKart(const Kart **minKart, float *minDistSquared,
btVector3 *minDelta, const Kart* inFrontOf=NULL,
const bool backwards=false) const;
/** Returns information on the parameters needed to hit a target kart
moving at constant velocity and direction for a given speed in the
XY-plane.
*/
void getLinearKartItemIntersection(const btVector3 origin, const Kart *target_kart,
float item_XY_velocity, float gravity,
float *fire_angle, float *up_velocity, float *time);
/** init bullet for moving objects like projectiles */
void createPhysics(float y_offset,
const btVector3 &velocity,