item intersection uses y_offset, hat initialised properly and some redundant code removed.

git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/irrlicht@3850 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
davemk 2009-08-13 12:12:22 +00:00
parent 1033bfdf59
commit c27a807e64
4 changed files with 83 additions and 105 deletions

View File

@ -48,7 +48,7 @@ Cake::Cake (Kart *kart) : Flyable(kart, POWERUP_CAKE)
// 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 /= 3.6f; //when going backwards, decrease speed of cake by less
m_speed += 16.0f;
@ -80,14 +80,10 @@ Cake::Cake (Kart *kart) : Flyable(kart, POWERUP_CAKE)
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]);
getLinearKartItemIntersection (kart->getTrans().getOrigin(), closest_kart,
m_speed, m_gravity, y_offset,
&fire_angle, &up_velocity, &time_estimated);
// apply transformation to the bullet object (without pitch)
btMatrix3x3 m;
@ -108,6 +104,9 @@ Cake::Cake (Kart *kart) : Flyable(kart, POWERUP_CAKE)
new btCylinderShape(0.5f*m_extend), -m_gravity,
true /* rotation */, false /* backwards */, &trans);
//do not adjust height according to terrain
setAdjustZVelocity(false);
m_body->setActivationState(DISABLE_DEACTIVATION);
m_body->applyTorque( btVector3(5,-3,7) );
@ -133,43 +132,31 @@ void Cake::init(const lisp::Lisp* lisp, scene::IMesh *cake_model)
// -----------------------------------------------------------------------------
void Cake::update(float dt)
{
//The following commented out code adds a lock on to the cake. It is kept
//because it shows how to lock on to a moving target precisely with the
//intersection algorithm and may be one day useful for something else.
/*
if(m_target != NULL)
{
/*
// correct direction to go towards aimed kart
btTransform my_trans = getTrans();
btTransform target = m_target->getTrans();
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,
btVector3 origin = my_trans.getOrigin() - m_target->getNormal() * 0.5 * m_target->getKartHeight();
getLinearKartItemIntersection (origin, m_target,
m_speed, m_gravity, 0,
&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();
pullForce.setZ(0);
pullForce.normalize();
pullForce *= 10;
m_body->applyCentralImpulse( pullForce );
*/
/*
// if over aimed kart, pull down
if(fabsf(my_trans.getOrigin().getX() - target.getOrigin().getX()) < 5.0 &&
fabsf(my_trans.getOrigin().getY() - target.getOrigin().getY()) < 5.0)
{
m_body->applyCentralForce( btVector3(0, 0, -20.0f) );
}
*/
}
*/
Flyable::update(dt);
} // update

View File

@ -64,7 +64,7 @@ Flyable::Flyable(Kart *kart, PowerupType type, float mass) : Moveable()
m_time_since_thrown = 0;
m_owner_has_temporary_immunity = true;
m_max_lifespan = -1;
// Add the graphical model
setNode(irr_driver->addMesh(m_st_model[type]));
} // Flyable
@ -72,7 +72,7 @@ Flyable::Flyable(Kart *kart, PowerupType type, float mass) : Moveable()
// ----------------------------------------------------------------------------
void Flyable::createPhysics(float y_offset, const btVector3 &velocity,
btCollisionShape *shape, const float gravity,
const bool rotates, const bool turn_around,
const bool rotates, const bool turn_around,
const btTransform* customDirection)
{
// Get Kart heading direction
@ -83,7 +83,7 @@ void Flyable::createPhysics(float y_offset, const btVector3 &velocity,
offset_transform.setIdentity();
btVector3 offset=btVector3(0,y_offset,m_average_height);
offset_transform.setOrigin(offset);
// turn around
if(turn_around)
{
@ -93,7 +93,7 @@ void Flyable::createPhysics(float y_offset, const btVector3 &velocity,
turn_around_trans.setRotation(btQuaternion(btVector3(0, 0, 1), M_PI));
trans *= turn_around_trans;
}
trans *= offset_transform;
m_shape = shape;
@ -115,7 +115,7 @@ void Flyable::createPhysics(float y_offset, const btVector3 &velocity,
} // createPhysics
// -----------------------------------------------------------------------------
void Flyable::init(const lisp::Lisp* lisp, scene::IMesh *model,
void Flyable::init(const lisp::Lisp* lisp, scene::IMesh *model,
PowerupType type)
{
m_st_speed[type] = 25.0f;
@ -146,37 +146,37 @@ void Flyable::getClosestKart(const Kart **minKart, float *minDistSquared,
btVector3 *minDelta, const Kart* inFrontOf, const bool backwards) const
{
btTransform tProjectile = (inFrontOf != NULL ? inFrontOf->getTrans() : getTrans());
*minDistSquared = -1.0f;
*minKart = NULL;
for(unsigned int i=0 ; i<race_manager->getNumKarts(); i++ )
{
Kart *kart = RaceManager::getKart(i);
if(kart->isEliminated() || kart == m_owner || kart->isRescue() ) continue;
btTransform t=kart->getTrans();
btVector3 delta = t.getOrigin()-tProjectile.getOrigin();
float distance2 = delta.length2();
if(inFrontOf != NULL)
{
// Ignore karts behind the current one
btVector3 to_target = kart->getXYZ() - inFrontOf->getXYZ();
const float distance = to_target.length();
if(distance > 50) continue; // kart too far, don't aim at it
btTransform trans = inFrontOf->getTrans();
// get heading=trans.getBasis*(0,1,0) ... so save the multiplication:
btVector3 direction(trans.getBasis()[0][1],
trans.getBasis()[1][1],
trans.getBasis()[2][1]);
const float angle = to_target.angle( backwards ? -direction : direction );
if(fabsf(angle) > 1) continue;
}
if(distance2 < *minDistSquared || *minDistSquared < 0 /* not yet set */)
{
*minDistSquared = distance2;
@ -184,54 +184,57 @@ void Flyable::getClosestKart(const Kart **minKart, float *minDistSquared,
*minDelta = delta;
}
} // for i<getNumKarts
} // getClosestKart
//-----------------------------------------------------------------------------
void Flyable::getLinearKartItemIntersection (const btVector3 origin, const Kart *target_kart,
float item_XY_speed, float gravity,
float item_XY_speed, float gravity, float y_offset,
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();
btVector3 relative_target_kart_loc = target_kart->getTrans().getOrigin() - origin;
btTransform trans = target_kart->getTrans();
Vec3 target_direction(trans.getBasis()[0][1],
trans.getBasis()[1][1],
trans.getBasis()[2][1]);
btVector3 target_direction(trans.getBasis()[0][1],
trans.getBasis()[1][1],
trans.getBasis()[2][1]);
float dx = relative_target_kart_loc.getX();
float dy = relative_target_kart_loc.getY();
float dz = relative_target_kart_loc.getZ();
float gx = target_direction.getX();
float gy = target_direction.getY();
float gz = target_direction.getZ();
float target_kart_speed = target_direction.length_2d() * target_kart->getSpeed(); //Projected onto X-Y plane
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 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);
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;
if (fire_th > M_PI)
fire_th -= M_PI;
else
fire_th += M_PI;
//createPhysics offset
time -= y_offset / hypotf(a, b);
*fire_angle = fire_th;
*up_velocity = (0.5f * time * gravity) + (dz / time) + (gz * target_kart->getSpeed());
*up_velocity = (0.5 * time * gravity) + (dz / time) + (gz * target_kart->getSpeed());
*time_estimated = time;
}
@ -240,9 +243,9 @@ void Flyable::update(float dt)
{
m_time_since_thrown += dt;
if(m_max_lifespan > -1 && m_time_since_thrown > m_max_lifespan) hit(NULL);
if(m_exploded) return;
Vec3 pos=getBody()->getWorldTransform().getOrigin();
TerrainInfo::update(pos);
@ -280,7 +283,7 @@ void Flyable::update(float dt)
// -----------------------------------------------------------------------------
/** Updates the position of a projectile based on information received frmo the
* server.
* server.
*/
void Flyable::updateFromServer(const FlyableInfo &f, float dt)
{
@ -299,8 +302,8 @@ void Flyable::updateFromServer(const FlyableInfo &f, float dt)
*/
bool Flyable::isOwnerImmunity(const Kart* kart_hit) const
{
return m_owner_has_temporary_immunity &&
kart_hit == m_owner &&
return m_owner_has_temporary_immunity &&
kart_hit == m_owner &&
m_time_since_thrown < 2.0f;
} // isOwnerImmunity
@ -309,7 +312,7 @@ void Flyable::hit(Kart *kart_hit, PhysicalObject* object)
{
// the owner of this flyable should not be hit by his own flyable
if(m_exploded || isOwnerImmunity(kart_hit)) return;
m_has_hit_something=true;
// Notify the projectile manager that this rocket has hit something.
// The manager will create the appropriate explosion object.
@ -324,10 +327,10 @@ void Flyable::hit(Kart *kart_hit, PhysicalObject* object)
for ( unsigned int i = 0 ; i < race_manager->getNumKarts() ; i++ )
{
Kart *kart = RaceManager::getKart(i);
// Handle the actual explosion. The kart that fired a flyable will
// Handle the actual explosion. The kart that fired a flyable will
// only be affected if it's a direct hit. This allows karts to use
// rockets on short distance.
if(m_owner!=kart || m_owner==kart_hit)
if(m_owner!=kart || m_owner==kart_hit)
{
// Set a flag it if was a direct hit.
kart->handleExplosion(getXYZ(), kart==kart_hit);

View File

@ -42,13 +42,13 @@ private:
bool m_has_hit_something;
/** This flag is used to avoid that a rocket explodes mode than once.
* It can happen that more than one collision between a rocket and
* a track or kart is reported by the physics. */
* a track or kart is reported by the physics. */
bool m_exploded;
/** If this flag is set, the Z velocity of the kart will not be
* adjusted in case that the objects is too high or too low above the
* adjusted in case that the objects is too high or too low above the
* terrain. Otherwise gravity will not work correctly on this object. */
bool m_adjust_z_velocity;
protected:
Kart* m_owner; // the kart which released this flyable
btCollisionShape *m_shape;
@ -59,7 +59,7 @@ protected:
float m_speed;
float m_mass;
btVector3 m_extend;
// The flyable class stores the values for each flyable type, e.g.
// The flyable class stores the values for each flyable type, e.g.
// speed, min_height, max_height. These variables must be static,
// so we need arrays of these variables to have different values
// for bowling balls, missiles, ...
@ -67,27 +67,27 @@ protected:
static scene::IMesh *m_st_model[POWERUP_MAX]; // 3d model
static float m_st_min_height[POWERUP_MAX]; // min height above track
static float m_st_max_height[POWERUP_MAX]; // max height above track
static float m_st_force_updown[POWERUP_MAX]; // force pushing up/down
static float m_st_force_updown[POWERUP_MAX]; // force pushing up/down
static btVector3 m_st_extend[POWERUP_MAX]; // size of the model
/** time since thrown. used so a kart can't hit himself when trying something,
and also to put some time limit to some collectibles */
float m_time_since_thrown;
/** set to something > -1 if this flyable should auto-destrcut after a while */
float m_max_lifespan;
/** if set to true, the kart that throwns this flyable can't collide with it
for a short time */
bool m_owner_has_temporary_immunity;
/** Returns information on what is the closest kart and at what
distance it is. All 3 parameters first are of type 'out'.
'inFrontOf' can be set if you wish to know the closest
kart in front of some karts (will ignore those behind).
Useful e.g. for throwing projectiles in front only.
*/
void getClosestKart(const Kart **minKart, float *minDistSquared,
void getClosestKart(const Kart **minKart, float *minDistSquared,
btVector3 *minDelta, const Kart* inFrontOf=NULL,
const bool backwards=false) const;
@ -96,25 +96,25 @@ protected:
XY-plane.
*/
void getLinearKartItemIntersection(const btVector3 origin, const Kart *target_kart,
float item_XY_velocity, float gravity,
float item_XY_velocity, float gravity, float y_offset,
float *fire_angle, float *up_velocity, float *time);
/** init bullet for moving objects like projectiles */
void createPhysics(float y_offset,
void createPhysics(float y_offset,
const btVector3 &velocity,
btCollisionShape *shape, const float gravity=0.0f,
const bool rotates=false, const bool turn_around=false,
const bool rotates=false, const bool turn_around=false,
const btTransform* customDirection=NULL);
public:
Flyable (Kart* kart, PowerupType type, float mass=1.0f);
virtual ~Flyable ();
/** Enables/disables adjusting ov velocity depending on height above
/** Enables/disables adjusting ov velocity depending on height above
* terrain. Missiles can 'follow the terrain' with this adjustment,
* but gravity will basically be disabled. */
void setAdjustZVelocity(bool f) { m_adjust_z_velocity = f; }
static void init (const lisp::Lisp* lisp, scene::IMesh *model,
static void init (const lisp::Lisp* lisp, scene::IMesh *model,
PowerupType type);
virtual void update (float);
void updateFromServer(const FlyableInfo &f, float dt);
@ -122,13 +122,13 @@ public:
virtual void hitTrack () {};
virtual void hit (Kart* kart, PhysicalObject* obj=NULL);
bool hasHit () { return m_has_hit_something; }
/** Indicates that something was hit and that this object must
/** Indicates that something was hit and that this object must
* be removed. */
void setHasHit () { m_has_hit_something = true; }
void reset () { Moveable::reset(); }
bool isOwnerImmunity(const Kart *kart_hit) const;
virtual int getExplosionSound() const { return SFXManager::SOUND_EXPLOSION; }
/** Indicates if an explosion needs to be added if this flyable
/** Indicates if an explosion needs to be added if this flyable
* is removed. */
virtual bool needsExplosion() const {return true;}
}; // Flyable

View File

@ -65,7 +65,7 @@ Plunger::Plunger(Kart *kart) : Flyable(kart, POWERUP_PLUNGER)
float fire_angle = 0.0f;
float time_estimated = 0.0f;
getLinearKartItemIntersection (kart->getTrans().getOrigin(), closest_kart,
plunger_speed, gravity,
plunger_speed, gravity, y_offset,
&fire_angle, &up_velocity, &time_estimated);
// apply transformation to the bullet object (without pitch)
@ -86,6 +86,9 @@ Plunger::Plunger(Kart *kart) : Flyable(kart, POWERUP_PLUNGER)
new btCylinderShape(0.5f*m_extend), gravity, false /* rotates */, m_reverse_mode, &trans );
}
//adjust height according to terrain
setAdjustZVelocity(true);
// pulling back makes no sense in battle mode, since this mode is not a race.
// so in battle mode, always hide view
if( m_reverse_mode || race_manager->isBattleMode(race_manager->getMinorMode()) )
@ -129,23 +132,8 @@ void Plunger::update(float dt)
// 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;
float hat = getTrans().getOrigin().getZ()-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();
float heading = atan2f(-v.getX(), v.getY());
float pitch = getTerrainPitch (heading);
float vel_z = m_force_updown*(delta);
if (hat < m_max_height) // take into account pitch of surface
vel_z += v.length_2d()*tanf(pitch);
v.setZ(vel_z);
setVelocity(v);
} // update
// -----------------------------------------------------------------------------
@ -188,7 +176,7 @@ void Plunger::hit(Kart *kart, PhysicalObject *obj)
getNode()->setPosition(hell.toIrrVector());
}
RaceManager::getWorld()->getPhysics()->removeBody(getBody());
if(kart)
{
m_rubber_band->hit(kart);
@ -208,7 +196,7 @@ void Plunger::hit(Kart *kart, PhysicalObject *obj)
// -----------------------------------------------------------------------------
/** Called when the plunger hits the track. In this case, notify the rubber
* band, and remove the plunger (but keep it alive).
* band, and remove the plunger (but keep it alive).
*/
void Plunger::hitTrack()
{