Added support for physical objects triggering rescue on collision
(#163). Objects must be declared with 'reset="Y"' in order to trigger rescue. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@9910 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
parent
3e32b840bf
commit
2b805c7d69
@ -45,11 +45,13 @@ PhysicalObject::PhysicalObject(const XMLNode &xml_node)
|
|||||||
m_motion_state = NULL;
|
m_motion_state = NULL;
|
||||||
m_mass = 1;
|
m_mass = 1;
|
||||||
m_radius = -1;
|
m_radius = -1;
|
||||||
|
m_crash_reset = false;
|
||||||
|
|
||||||
std::string shape;
|
std::string shape;
|
||||||
xml_node.get("mass", &m_mass );
|
xml_node.get("mass", &m_mass );
|
||||||
xml_node.get("radius", &m_radius );
|
xml_node.get("radius", &m_radius );
|
||||||
xml_node.get("shape", &shape );
|
xml_node.get("shape", &shape );
|
||||||
|
xml_node.get("reset", &m_crash_reset);
|
||||||
|
|
||||||
m_body_type = MP_NONE;
|
m_body_type = MP_NONE;
|
||||||
if (shape=="cone" ||
|
if (shape=="cone" ||
|
||||||
|
@ -42,20 +42,26 @@ public:
|
|||||||
MP_CYLINDER_Y, MP_CYLINDER_X, MP_CYLINDER_Z,
|
MP_CYLINDER_Y, MP_CYLINDER_X, MP_CYLINDER_Z,
|
||||||
MP_BOX, MP_SPHERE};
|
MP_BOX, MP_SPHERE};
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
/** The shape of this object. */
|
/** The shape of this object. */
|
||||||
bodyTypes m_body_type;
|
bodyTypes m_body_type;
|
||||||
|
|
||||||
/** The bullet collision shape. */
|
/** The bullet collision shape. */
|
||||||
btCollisionShape *m_shape;
|
btCollisionShape *m_shape;
|
||||||
|
|
||||||
/** The corresponding bullet rigid body. */
|
/** The corresponding bullet rigid body. */
|
||||||
btRigidBody *m_body;
|
btRigidBody *m_body;
|
||||||
|
|
||||||
/** Bullet's motion state for this object. */
|
/** Bullet's motion state for this object. */
|
||||||
btDefaultMotionState *m_motion_state;
|
btDefaultMotionState *m_motion_state;
|
||||||
|
|
||||||
/** The mass of this object. */
|
/** The mass of this object. */
|
||||||
float m_mass;
|
float m_mass;
|
||||||
|
|
||||||
/** The pointer that is stored in the bullet rigid body back to
|
/** The pointer that is stored in the bullet rigid body back to
|
||||||
* this object. */
|
* this object. */
|
||||||
UserPointer m_user_pointer;
|
UserPointer m_user_pointer;
|
||||||
|
|
||||||
/** This is the initial position of the object for the physics. */
|
/** This is the initial position of the object for the physics. */
|
||||||
btTransform m_init_pos;
|
btTransform m_init_pos;
|
||||||
|
|
||||||
@ -66,6 +72,10 @@ protected:
|
|||||||
* details, but is supposed to be a sphere). In this case the radius
|
* details, but is supposed to be a sphere). In this case the radius
|
||||||
* can be set in the scene file. */
|
* can be set in the scene file. */
|
||||||
float m_radius;
|
float m_radius;
|
||||||
|
|
||||||
|
/** True if a kart colliding with this object should be rescued. */
|
||||||
|
bool m_crash_reset;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PhysicalObject (const XMLNode &node);
|
PhysicalObject (const XMLNode &node);
|
||||||
|
|
||||||
@ -76,12 +86,17 @@ public:
|
|||||||
const core::vector3df& scale);
|
const core::vector3df& scale);
|
||||||
|
|
||||||
virtual ~PhysicalObject ();
|
virtual ~PhysicalObject ();
|
||||||
|
virtual void reset ();
|
||||||
|
virtual void handleExplosion(const Vec3& pos, bool directHit);
|
||||||
void update (float dt);
|
void update (float dt);
|
||||||
void init ();
|
void init ();
|
||||||
virtual void reset ();
|
// ------------------------------------------------------------------------
|
||||||
/** Returns the rigid body of this physical object. */
|
/** Returns the rigid body of this physical object. */
|
||||||
btRigidBody *getBody () { return m_body; }
|
btRigidBody *getBody () { return m_body; }
|
||||||
virtual void handleExplosion(const Vec3& pos, bool directHit);
|
// ------------------------------------------------------------------------
|
||||||
|
/** Returns true if this object should trigger a rescue in a kart that
|
||||||
|
* hits it. */
|
||||||
|
bool isCrashReset() const { return m_crash_reset; }
|
||||||
}; // PhysicalObject
|
}; // PhysicalObject
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include "physics/btKart.hpp"
|
#include "physics/btKart.hpp"
|
||||||
#include "physics/btUprightConstraint.hpp"
|
#include "physics/btUprightConstraint.hpp"
|
||||||
#include "physics/irr_debug_drawer.hpp"
|
#include "physics/irr_debug_drawer.hpp"
|
||||||
|
#include "physics/physical_object.hpp"
|
||||||
#include "physics/triangle_mesh.hpp"
|
#include "physics/triangle_mesh.hpp"
|
||||||
#include "tracks/track.hpp"
|
#include "tracks/track.hpp"
|
||||||
|
|
||||||
@ -99,7 +100,7 @@ void Physics::removeKart(const Kart *kart)
|
|||||||
void Physics::update(float dt)
|
void Physics::update(float dt)
|
||||||
{
|
{
|
||||||
// Bullet can report the same collision more than once (up to 4
|
// Bullet can report the same collision more than once (up to 4
|
||||||
// contact points per collision. Additionally, more than one internal
|
// contact points per collision). Additionally, more than one internal
|
||||||
// substep might be taken, resulting in potentially even more
|
// substep might be taken, resulting in potentially even more
|
||||||
// duplicates. To handle this, all collisions (i.e. pair of objects)
|
// duplicates. To handle this, all collisions (i.e. pair of objects)
|
||||||
// are stored in a vector, but only one entry per collision pair
|
// are stored in a vector, but only one entry per collision pair
|
||||||
@ -110,33 +111,59 @@ void Physics::update(float dt)
|
|||||||
// 20 FPS (bullet default frequency is 60 HZ).
|
// 20 FPS (bullet default frequency is 60 HZ).
|
||||||
m_dynamics_world->stepSimulation(dt, 3);
|
m_dynamics_world->stepSimulation(dt, 3);
|
||||||
|
|
||||||
// Now handle the actual collision. Note: rockets can not be removed
|
// Now handle the actual collision. Note: flyables can not be removed
|
||||||
// inside of this loop, since the same rocket might hit more than one
|
// inside of this loop, since the same flyables might hit more than one
|
||||||
// other object. So, only a flag is set in the rockets, the actual
|
// other object. So only a flag is set in the flyables, the actual
|
||||||
// clean up is then done later in the projectile manager.
|
// clean up is then done later in the projectile manager.
|
||||||
std::vector<CollisionPair>::iterator p;
|
std::vector<CollisionPair>::iterator p;
|
||||||
for(p=m_all_collisions.begin(); p!=m_all_collisions.end(); ++p)
|
for(p=m_all_collisions.begin(); p!=m_all_collisions.end(); ++p)
|
||||||
{
|
{
|
||||||
if(p->a->is(UserPointer::UP_KART)) { // kart-kart collision
|
// Kart-kart collision
|
||||||
|
// --------------------
|
||||||
|
if(p->a->is(UserPointer::UP_KART))
|
||||||
|
{
|
||||||
Kart *a=p->a->getPointerKart();
|
Kart *a=p->a->getPointerKart();
|
||||||
Kart *b=p->b->getPointerKart();
|
Kart *b=p->b->getPointerKart();
|
||||||
race_state->addCollision(a->getWorldKartId(),
|
race_state->addCollision(a->getWorldKartId(),
|
||||||
b->getWorldKartId());
|
b->getWorldKartId());
|
||||||
KartKartCollision(p->a->getPointerKart(), p->b->getPointerKart());
|
KartKartCollision(p->a->getPointerKart(), p->b->getPointerKart());
|
||||||
|
continue;
|
||||||
} // if kart-kart collision
|
} // if kart-kart collision
|
||||||
else // now the first object must be a projectile
|
|
||||||
|
if(p->a->is(UserPointer::UP_PHYSICAL_OBJECT))
|
||||||
{
|
{
|
||||||
if(p->b->is(UserPointer::UP_TRACK)) // must be projectile hit track
|
// Kart hits physical object
|
||||||
|
// -------------------------
|
||||||
|
PhysicalObject *obj = p->a->getPointerPhysicalObject();
|
||||||
|
if(obj->isCrashReset())
|
||||||
{
|
{
|
||||||
|
Kart *kart = p->b->getPointerKart();
|
||||||
|
kart->forceRescue();
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// now the first object must be a projectile
|
||||||
|
// =========================================
|
||||||
|
if(p->b->is(UserPointer::UP_TRACK))
|
||||||
|
{
|
||||||
|
// Projectile hits track
|
||||||
|
// ---------------------
|
||||||
p->a->getPointerFlyable()->hitTrack();
|
p->a->getPointerFlyable()->hitTrack();
|
||||||
}
|
}
|
||||||
else if(p->b->is(UserPointer::UP_PHYSICAL_OBJECT))
|
else if(p->b->is(UserPointer::UP_PHYSICAL_OBJECT))
|
||||||
{
|
{
|
||||||
p->a->getPointerFlyable()->hit(NULL, p->b->getPointerPhysicalObject());
|
// Projectile hits physical object
|
||||||
|
// -------------------------------
|
||||||
|
p->a->getPointerFlyable()
|
||||||
|
->hit(NULL, p->b->getPointerPhysicalObject());
|
||||||
|
|
||||||
}
|
}
|
||||||
else if(p->b->is(UserPointer::UP_KART)) // projectile hit kart
|
else if(p->b->is(UserPointer::UP_KART))
|
||||||
{
|
{
|
||||||
|
// Projectile hits kart
|
||||||
|
// --------------------
|
||||||
// Only explode a bowling ball if the target is
|
// Only explode a bowling ball if the target is
|
||||||
// not invulnerable
|
// not invulnerable
|
||||||
if(p->a->getPointerFlyable()->getType()
|
if(p->a->getPointerFlyable()->getType()
|
||||||
@ -144,12 +171,13 @@ void Physics::update(float dt)
|
|||||||
!p->b->getPointerKart()->isInvulnerable() )
|
!p->b->getPointerKart()->isInvulnerable() )
|
||||||
p->a->getPointerFlyable()->hit(p->b->getPointerKart());
|
p->a->getPointerFlyable()->hit(p->b->getPointerKart());
|
||||||
}
|
}
|
||||||
else // projectile hits projectile
|
else
|
||||||
{
|
{
|
||||||
|
// Projectile hits projectile
|
||||||
|
// --------------------------
|
||||||
p->a->getPointerFlyable()->hit(NULL);
|
p->a->getPointerFlyable()->hit(NULL);
|
||||||
p->b->getPointerFlyable()->hit(NULL);
|
p->b->getPointerFlyable()->hit(NULL);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} // for all p in m_all_collisions
|
} // for all p in m_all_collisions
|
||||||
} // update
|
} // update
|
||||||
|
|
||||||
@ -161,15 +189,16 @@ void Physics::update(float dt)
|
|||||||
bool Physics::projectKartDownwards(const Kart *k)
|
bool Physics::projectKartDownwards(const Kart *k)
|
||||||
{
|
{
|
||||||
btVector3 hell(0, -10000, 0);
|
btVector3 hell(0, -10000, 0);
|
||||||
return k->getVehicle()->projectVehicleToSurface(hell, true /*allow translation*/);
|
return k->getVehicle()->projectVehicleToSurface(hell,
|
||||||
|
/*allow translation*/true);
|
||||||
} //projectKartsDownwards
|
} //projectKartsDownwards
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
/** Handles the special case of two karts colliding with each other, which means
|
/** Handles the special case of two karts colliding with each other, which
|
||||||
* that bombs must be passed on. If both karts have a bomb, they'll explode
|
* means that bombs must be passed on. If both karts have a bomb, they'll
|
||||||
* immediately. This function is called from physics::update() on the server
|
* explode immediately. This function is called from physics::update() on the
|
||||||
* and if no networking is used, and from race_state on the client to replay
|
* server and if no networking is used, and from race_state on the client to
|
||||||
* what happened on the server.
|
* replay what happened on the server.
|
||||||
* \param kartA First kart involved in the collision.
|
* \param kartA First kart involved in the collision.
|
||||||
* \param kartB Second kart involved in the collision.
|
* \param kartB Second kart involved in the collision.
|
||||||
*/
|
*/
|
||||||
@ -253,9 +282,10 @@ void Physics::KartKartCollision(Kart *kartA, Kart *kartB)
|
|||||||
* physics time step might miss some collisions (when more than one internal
|
* physics time step might miss some collisions (when more than one internal
|
||||||
* time step was done, and the collision is added and removed). So this
|
* time step was done, and the collision is added and removed). So this
|
||||||
* function stores all collisions in a list, which is then handled after the
|
* function stores all collisions in a list, which is then handled after the
|
||||||
* actual physics timestep. This list only stores a collision, if it's not
|
* actual physics timestep. This list only stores a collision if it's not
|
||||||
* already in the list, so a collisions which is reported more than once is
|
* already in the list, so a collisions which is reported more than once is
|
||||||
* nevertheless only handled once.
|
* nevertheless only handled once.
|
||||||
|
* The list of collision
|
||||||
* Parameters: see bullet documentation for details.
|
* Parameters: see bullet documentation for details.
|
||||||
*/
|
*/
|
||||||
btScalar Physics::solveGroup(btCollisionObject** bodies, int numBodies,
|
btScalar Physics::solveGroup(btCollisionObject** bodies, int numBodies,
|
||||||
@ -292,6 +322,7 @@ btScalar Physics::solveGroup(btCollisionObject** bodies, int numBodies,
|
|||||||
// FIXME: Must be a moving physics object
|
// FIXME: Must be a moving physics object
|
||||||
// FIXME: A rocket should explode here!
|
// FIXME: A rocket should explode here!
|
||||||
if(!upA || !upB) continue;
|
if(!upA || !upB) continue;
|
||||||
|
|
||||||
// 1) object A is a track
|
// 1) object A is a track
|
||||||
// =======================
|
// =======================
|
||||||
if(upA->is(UserPointer::UP_TRACK))
|
if(upA->is(UserPointer::UP_TRACK))
|
||||||
@ -324,28 +355,39 @@ btScalar Physics::solveGroup(btCollisionObject** bodies, int numBodies,
|
|||||||
kart->crashed(NULL, m); // Kart hit track
|
kart->crashed(NULL, m); // Kart hit track
|
||||||
}
|
}
|
||||||
else if(upB->is(UserPointer::UP_FLYABLE))
|
else if(upB->is(UserPointer::UP_FLYABLE))
|
||||||
m_all_collisions.push_back(upB, upA); // 2.1 projectile hits kart
|
// 2.1 projectile hits kart
|
||||||
|
m_all_collisions.push_back(upB, upA);
|
||||||
else if(upB->is(UserPointer::UP_KART))
|
else if(upB->is(UserPointer::UP_KART))
|
||||||
m_all_collisions.push_back(upA, upB); // 2.2 kart hits kart
|
// 2.2 kart hits kart
|
||||||
|
m_all_collisions.push_back(upA, upB);
|
||||||
|
else if(upB->is(UserPointer::UP_PHYSICAL_OBJECT))
|
||||||
|
// 2.3 kart hits physical object
|
||||||
|
m_all_collisions.push_back(upB, upA);
|
||||||
}
|
}
|
||||||
// 3) object is a projectile
|
// 3) object is a projectile
|
||||||
// =========================
|
// =========================
|
||||||
else if(upA->is(UserPointer::UP_FLYABLE))
|
else if(upA->is(UserPointer::UP_FLYABLE))
|
||||||
{
|
{
|
||||||
if(upB->is(UserPointer::UP_TRACK ) || // 3.1) projectile hits track
|
// 3.1) projectile hits track
|
||||||
upB->is(UserPointer::UP_FLYABLE ) || // 3.2) projectile hits projectile
|
// 3.2) projectile hits projectile
|
||||||
upB->is(UserPointer::UP_PHYSICAL_OBJECT) || // 3.3) projectile hits projectile
|
// 3.3) projectile hits physical object
|
||||||
upB->is(UserPointer::UP_KART ) ) // 3.4) projectile hits kart
|
// 3.4) projectile hits kart
|
||||||
|
if(upB->is(UserPointer::UP_TRACK ) ||
|
||||||
|
upB->is(UserPointer::UP_FLYABLE ) ||
|
||||||
|
upB->is(UserPointer::UP_PHYSICAL_OBJECT) ||
|
||||||
|
upB->is(UserPointer::UP_KART ) )
|
||||||
{
|
{
|
||||||
m_all_collisions.push_back(upA, upB);
|
m_all_collisions.push_back(upA, upB);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Object is a physical object
|
||||||
|
// ===========================
|
||||||
else if(upA->is(UserPointer::UP_PHYSICAL_OBJECT))
|
else if(upA->is(UserPointer::UP_PHYSICAL_OBJECT))
|
||||||
{
|
{
|
||||||
if(upB->is(UserPointer::UP_FLYABLE))
|
if(upB->is(UserPointer::UP_FLYABLE))
|
||||||
{
|
|
||||||
m_all_collisions.push_back(upB, upA);
|
m_all_collisions.push_back(upB, upA);
|
||||||
}
|
else if(upB->is(UserPointer::UP_KART))
|
||||||
|
m_all_collisions.push_back(upA, upB);
|
||||||
}
|
}
|
||||||
else assert("Unknown user pointer"); // 4) Should never happen
|
else assert("Unknown user pointer"); // 4) Should never happen
|
||||||
} // for i<numManifolds
|
} // for i<numManifolds
|
||||||
|
Loading…
x
Reference in New Issue
Block a user