1) Fixed zipper (settings for further tuning in stk_config.data).

2) Fixed bug in collision detection (a kart-kart crash could cause
   a sigsegv).
3) Fixed bug in track loader, which caused somer track objects (e.g.
   zipper in bsod castle) not to get the correct pitch/roll, causing
   them to 'stick out')
4) Fixed wheelie handling for AI (though wheelies are still disabled
   by default, change wheelie-max-speed-ratio to 0.5 to test).
5) Some cleanup of non-bullet code.



git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/trunk/supertuxkart@1370 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hikerstk 2008-01-01 14:30:39 +00:00
parent 56e24ec8a6
commit a5e2ef24d5
23 changed files with 358 additions and 226 deletions

View File

@ -22,6 +22,8 @@
(bomb-time 30.0 ) ;; time till a bomb explodes
(bomb-time-increase -5.0 ) ;; time added to timer when bomb is passed on
(anvil-time 2.0 ) ;; time an anvil is active
(zipper-time 5.0 ) ;; time a zipper is active
(zipper-force 800.0 ) ;; additional zipper force
(shortcut-road-distance 23.0 ) ;; max. distance from side of road to be still
;; considered on the road (otherwise shortcut)
;; usually 5 is a good value, but for the math class

View File

@ -77,6 +77,8 @@ supertuxkart_SOURCES = main.cpp \
auto_kart.hpp \
player_kart.cpp player_kart.hpp \
terrain_info.cpp terrain_info.hpp \
triangle_mesh.cpp triangle_mesh.hpp \
user_pointer.hpp \
flyable.cpp flyable.hpp \
missile.cpp missile.hpp \
homing.cpp homing.hpp \

View File

@ -122,7 +122,7 @@ void Attachment::moveBombFromTo(Kart *from, Kart *to)
} // moveBombFromTo
//-----------------------------------------------------------------------------
void Attachment::update(float dt, sgCoord *velocity)
void Attachment::update(float dt)
{
if(m_type==ATTACH_NOTHING) return;
m_time_left -=dt;

View File

@ -74,7 +74,7 @@ public:
?stk_config->m_anvil_speed_factor:1.0f;
}
void hitGreenHerring();
void update (float dt, sgCoord *velocity);
void update (float dt);
void moveBombFromTo(Kart *from, Kart *to);
};

View File

@ -52,6 +52,7 @@ Flyable::Flyable(Kart *kart, CollectableType type) : Moveable(false)
m_shape = NULL;
m_mass = 1.0f;
setUserPointerType(UP_PROJECTILE);
// Add the graphical model
ssgTransform *m = getModelTransform();
m->addKid(m_st_model[type]);
@ -88,7 +89,7 @@ void Flyable::createPhysics(const btVector3& offset, const btVector3 velocity)
trans *= offset_transform;
m_shape = createShape(); // get shape
createBody(m_mass, trans, m_shape, Moveable::MOV_PROJECTILE);
createBody(m_mass, trans, m_shape, UserPointer::UP_PROJECTILE);
world->getPhysics()->addBody(getBody());
// Simplified rockets: no gravity
@ -193,8 +194,6 @@ void Flyable::placeModel()
float m[4][4];
t.getOpenGLMatrix((float*)&m);
sgSetCoord(&m_curr_pos, m);
const btVector3 &v=m_body->getLinearVelocity();
sgSetVec3(m_velocity.xyz, v.x(), v.y(), v.z());
Moveable::placeModel();
} // placeModel

View File

@ -893,6 +893,10 @@
RelativePath="../../../src\traffic.cpp"
>
</File>
<File
RelativePath="..\..\triangle_mesh.cpp"
>
</File>
<File
RelativePath="../../../src\user_config.cpp"
>
@ -1307,10 +1311,18 @@
RelativePath="../../../src\translation.hpp"
>
</File>
<File
RelativePath="..\..\triangle_mesh.hpp"
>
</File>
<File
RelativePath="../../../src\user_config.hpp"
>
</File>
<File
RelativePath="..\..\user_pointer.hpp"
>
</File>
<File
RelativePath="..\..\widget.hpp"
>

View File

@ -79,7 +79,7 @@ void KartParticleSystem::particle_create(int, Particle *p)
p -> m_time_to_live = 0.5 ; /* Droplets evaporate after 5 seconds */
const sgCoord* POS = m_kart->getCoord();
const sgCoord* VEL = m_kart->getVelocity();
const btVector3 VEL = m_kart->getVelocity();
const float X_DIRECTION = sgCos (POS->hpr[0] - 90.0f); // Point at the rear
const float Y_DIRECTION = sgSin (POS->hpr[0] - 90.0f); // Point at the rear
@ -89,7 +89,7 @@ void KartParticleSystem::particle_create(int, Particle *p)
p->m_pos[0] += X_DIRECTION * 0.7f;
p->m_pos[1] += Y_DIRECTION * 0.7f;
const float ABS_VEL = sqrt((VEL->xyz[0] * VEL->xyz[0]) + (VEL->xyz[1] * VEL->xyz[1]));
const float ABS_VEL = sqrt((VEL.getX() * VEL.getX()) + (VEL.getY() * VEL.getY()));
p->m_vel[0] = X_DIRECTION * -ABS_VEL/2;
p->m_vel[1] = Y_DIRECTION * -ABS_VEL/2;
@ -200,7 +200,7 @@ void Kart::createPhysics(ssgEntity *obj)
// --------------------
btTransform trans;
trans.setIdentity();
createBody(mass, trans, &m_kart_chassis, Moveable::MOV_KART);
createBody(mass, trans, &m_kart_chassis, UserPointer::UP_KART);
m_body->setDamping(m_kart_properties->getChassisLinearDamping(),
m_kart_properties->getChassisAngularDamping() );
@ -397,13 +397,6 @@ void Kart::reset()
placeModel();
} // reset
//-----------------------------------------------------------------------------
void Kart::handleZipper()
{
m_wheelie_angle = ZIPPER_ANGLE;
m_zipper_time_left = ZIPPER_TIME;
} // handleZipper
//-----------------------------------------------------------------------------
void Kart::doLapCounting ()
{
@ -530,29 +523,18 @@ void Kart::collectedHerring(Herring* herring)
sound_manager->playSfx(SOUND_FULL);
} // hitHerring
//-----------------------------------------------------------------------------
void Kart::doZipperProcessing (float dt)
{
if ( m_zipper_time_left > dt )
{
m_zipper_time_left -= dt ;
if ( m_velocity.xyz[1] < ZIPPER_VELOCITY )
m_velocity.xyz[1] = ZIPPER_VELOCITY ;
}
else m_zipper_time_left = 0.0f ;
} // doZipperProcessing
//-----------------------------------------------------------------------------
// Simulates gears
float Kart::getActualWheelForce()
{
float zipperF=(m_zipper_time_left>0.0f) ? stk_config->m_zipper_force : 0.0f;
const std::vector<float>& gear_ratio=m_kart_properties->getGearSwitchRatio();
for(unsigned int i=0; i<gear_ratio.size(); i++)
{
if(m_speed <= m_max_speed*gear_ratio[i])
return getMaxPower()*m_kart_properties->getGearPowerIncrease()[i];
return getMaxPower()*m_kart_properties->getGearPowerIncrease()[i]+zipperF;
}
return getMaxPower();
return getMaxPower()+zipperF;
} // getActualWheelForce
@ -610,9 +592,11 @@ void Kart::update (float dt)
m_time_since_stuck = 0.0f;
}
m_zipper_time_left = m_zipper_time_left>0.0f ? m_zipper_time_left-dt : 0.0f;
//m_wheel_position gives the rotation around the X-axis, and since velocity's
//timeframe is the delta time, we don't have to multiply it with dt.
m_wheel_position += m_velocity.xyz[1];
m_wheel_position += getVelocity().getY();
if ( m_rescue )
{
@ -639,7 +623,7 @@ void Kart::update (float dt)
//printf("Set %f %f %f\n",pos.getOrigin().x(),pos.getOrigin().y(),pos.getOrigin().z());
} // if m_rescue
m_attachment.update(dt, &m_velocity);
m_attachment.update(dt);
/*smoke drawing control point*/
if ( user_config->m_smoke )
@ -647,20 +631,22 @@ void Kart::update (float dt)
if (m_smoke_system != NULL)
m_smoke_system->update (dt);
} // user_config->smoke
doZipperProcessing (dt) ;
updatePhysics(dt);
sgCopyVec2 ( m_last_track_coords, m_curr_track_coords );
Moveable::update(dt);
btTransform trans;
getTrans(&trans);
btTransform trans=getTrans();
TerrainInfo::update(trans.getOrigin());
if (getHoT()==Track::NOHIT ||
(getMaterial()->isReset() && isOnGround()) )
{
forceRescue();
}
else if(getMaterial()->isZipper())
{
handleZipper();
}
else
{
for(int i=0; i<m_vehicle->getNumWheels(); i++)
@ -762,6 +748,11 @@ void Kart::update (float dt)
processSkidMarks();
} // update
//-----------------------------------------------------------------------------
void Kart::handleZipper()
{
m_zipper_time_left = stk_config->m_zipper_time;
} // handleZipper
//-----------------------------------------------------------------------------
#define sgn(x) ((x<0)?-1.0f:((x>0)?1.0f:0.0f))
@ -769,8 +760,7 @@ void Kart::update (float dt)
void Kart::draw()
{
float m[16];
btTransform t;
getTrans(&t);
btTransform t=getTrans();
t.getOpenGLMatrix(m);
btVector3 wire_color(0.5f, 0.5f, 0.5f);
@ -1223,8 +1213,6 @@ void Kart::placeModel ()
//printf(" is %f %f %f\n",t.getOrigin().x(),t.getOrigin().y(),t.getOrigin().z());
// Transfer the new position and hpr to m_curr_pos
sgSetCoord(&m_curr_pos, m);
const btVector3 &v=m_body->getLinearVelocity();
sgSetVec3(m_velocity.xyz, v.x(), v.y(), v.z());
}
sgCoord c ;
sgCopyCoord ( &c, &m_curr_pos ) ;
@ -1236,8 +1224,8 @@ void Kart::placeModel ()
Moveable::placeModel();
// Check if a kart needs to be rescued.
if((fabs(m_curr_pos.hpr[2])>60 &&
sgLengthVec3(m_velocity.xyz)<3.0f) || m_time_since_stuck > 2.0f)
if((fabs(m_curr_pos.hpr[2])>60 && getSpeed()<3.0f) ||
m_time_since_stuck > 2.0f)
{
m_rescue=true;
m_time_since_stuck=0.0f;
@ -1278,17 +1266,17 @@ void Kart::handleMagnet(float cdist, int closest)
sgHPRfromVec3 ( getCoord()->hpr, vec ) ;
float tgt_velocity = world->getKart(closest)->getVelocity()->xyz[1] ;
float tgt_velocity = world->getKart(closest)->getVelocity().getY();
//JH FIXME: that should probably be changed, e.g. by increasing the throttle
// to something larger than 1???
if (cdist > stk_config->m_magnet_min_range_sq)
{
if ( m_velocity.xyz[1] < tgt_velocity )
m_velocity.xyz[1] = tgt_velocity * 1.4f;
if ( getSpeed ()< tgt_velocity )
;//FIXME m_velocity.xyz[1] = tgt_velocity * 1.4f;
}
else
m_velocity.xyz[1] = tgt_velocity ;
;//FIXME m_velocity.xyz[1] = tgt_velocity ;
} // handleMagnet
//-----------------------------------------------------------------------------

View File

@ -78,7 +78,6 @@ protected:
KartControl m_controls; // The position of the karts controls
int m_track_sector; // index in driveline, special values
// e.g. UNKNOWN_SECTOR can be negative!
float m_zipper_time_left;
sgVec2 m_last_track_coords;
sgVec3 m_curr_track_coords;
sgVec3 m_velocity_wc; // velocity in world coordinates
@ -87,7 +86,8 @@ protected:
bool m_skid_rear; // true if rear tires are skidding
float m_max_speed; // maximum speed of the kart, computed from
float m_max_speed_reverse_ratio;
float m_wheelie_angle ;
float m_wheelie_angle;
float m_zipper_time_left; // zipper time left
float m_lap_start_time; // Time at start of a new lap
float m_kart_length; // length of kart
char m_fastest_lap_message[255];
@ -139,34 +139,29 @@ protected:
void load_wheels (ssgBranch* obj);
public:
Kart(const KartProperties* kartProperties_, int position_, sgCoord init_pos);
virtual ~Kart();
void loadData();
void placeModel ();
const KartProperties* getKartProperties() const
{ return m_kart_properties; }
Kart(const KartProperties* kartProperties_, int position_,
sgCoord init_pos);
virtual ~Kart();
void loadData();
void placeModel ();
const KartProperties*
getKartProperties () const { return m_kart_properties; }
void setKartProperties (const KartProperties *kp)
{ m_kart_properties=kp;}
{ m_kart_properties=kp; }
void attach (attachmentType attachment_, float time)
{ m_attachment.set(attachment_, time);}
void gotZipper (float angle, float time)
{
m_wheelie_angle=angle;
m_zipper_time_left=time;
}
{ m_attachment.set(attachment_, time); }
void setCollectable (CollectableType t, int n)
{ m_collectable.set(t, n); }
void setPosition (int p) {m_race_position = p; }
int getSector () { return m_track_sector; }
float getDistanceDownTrack() { return m_curr_track_coords[1]; }
float getDistanceToCenter () { return m_curr_track_coords[0]; }
Attachment *getAttachment () { return &m_attachment; }
{ m_collectable.set(t, n); }
void setPosition (int p)
{ m_race_position = p; }
int getSector () const { return m_track_sector; }
float getDistanceDownTrack() const { return m_curr_track_coords[1]; }
float getDistanceToCenter () const { return m_curr_track_coords[0]; }
Attachment *getAttachment () { return &m_attachment; }
void setAttachmentType (attachmentType t, float time_left=0.0f,
Kart*k=NULL)
{ m_attachment.set(t, time_left, k); }
Collectable *getCollectable () { return &m_collectable; }
Collectable *getCollectable () { return &m_collectable; }
int getNumCollectables () const { return m_collectable.getNum();}
int getNumHerring () const { return m_num_herrings_gobbled;}
int getLap () const { return m_race_lap; }
@ -179,7 +174,6 @@ public:
void processSkidMarks ();
void getClosestKart (float *cdist, int *closest);
void handleMagnet (float cdist, int closest);
void doZipperProcessing (float dt);
void updatePhysics (float dt);
float NormalizedLateralForce(float alpha, float corner) const;

View File

@ -71,17 +71,15 @@ void Moveable::reset ()
m_crashed = false;
m_material_hot = NULL;
m_normal_hot = NULL;
sgZeroVec3 ( m_velocity.xyz ) ;
sgZeroVec3 ( m_velocity.hpr ) ;
if(m_body) m_body->setLinearVelocity(btVector3(0.0, 0.0, 0.0));
sgCopyCoord ( &m_curr_pos, &m_reset_pos ) ;
sgZeroVec3 ( m_abs_velocity ) ;
} // reset
//-----------------------------------------------------------------------------
void Moveable::createBody(float mass, btTransform& trans,
btCollisionShape *shape, MoveableType m) {
btCollisionShape *shape,
UserPointer::UserPointerType t) {
btVector3 inertia;
m_transform = trans;
@ -93,7 +91,7 @@ void Moveable::createBody(float mass, btTransform& trans,
m_body = new btRigidBody(mass, m_motion_state,
shape, inertia);
m_body->setUserPointer(this);
setMoveableType(m);
setUserPointerType(t);
} // createBody
//-----------------------------------------------------------------------------
@ -118,29 +116,17 @@ void Moveable::update (float dt)
sgCopyCoord(&m_velocity, &tmp);
m_velocity.xyz[2]=DUMMY;
#else
sgCopyCoord(&m_velocity, &tmp);
m_velocityLC.setValue(tmp.xyz[0],tmp.xyz[1],tmp.xyz[2]);
#endif
}
else
{
sgCopyCoord(&(m_history_velocity[history->GetCurrentIndex()]), &m_velocity);
m_history_velocity[history->GetCurrentIndex()].xyz[0]=m_velocityLC.getX();
m_history_velocity[history->GetCurrentIndex()].xyz[1]=m_velocityLC.getY();
m_history_velocity[history->GetCurrentIndex()].xyz[2]=m_velocityLC.getZ();
}
} // if m_history_velocity
sgMat4 result;
updatePosition(dt,result);
sgVec3 start ; sgCopyVec3 (start, m_curr_pos.xyz );
sgVec3 end ; sgCopyVec3 (end , result[3] );
sgCopyVec3 (result[3], end) ;
sgVec3 prev_pos;
sgCopyVec3(prev_pos, m_curr_pos.xyz);
sgSetCoord (&m_curr_pos, result);
sgSubVec3 (m_abs_velocity, m_curr_pos.xyz, prev_pos);
if(m_history_position)
{
if(user_config->m_replay_history)
@ -170,6 +156,7 @@ void Moveable::update (float dt)
}
} // if m_history_position
m_velocityLC = getVelocity()*getTrans().getBasis();
placeModel();
m_first_time = false ;
} // update
@ -181,22 +168,6 @@ void Moveable::placeModel()
m_model_transform->setTransform(&m_curr_pos);
} // placeModel
//-----------------------------------------------------------------------------
/**
* Computes the new position and hpr of the kart after a single time step.
*/
void Moveable::updatePosition(float dt, sgMat4 result)
{
sgCoord scaled_velocity ;
sgMat4 delta, mat;
/* Scale velocities to current time step. */
sgScaleVec3 (scaled_velocity.xyz, m_velocity.xyz, dt);
sgScaleVec3 (scaled_velocity.hpr, m_velocity.hpr, dt);
sgMakeCoordMat4(delta, & scaled_velocity );
sgMakeCoordMat4(mat , & m_curr_pos );
sgMultMat4 (result, mat, delta );
} // updatePosition
//-----------------------------------------------------------------------------
void Moveable::WriteHistory(char* s, int kartNumber, int indx)
{

View File

@ -23,9 +23,8 @@
#include <plib/ssg.h>
#include "material.hpp"
#ifdef BULLET
#include "btBulletDynamicsCommon.h"
#endif
#include "user_pointer.hpp"
/* Limits of Kart performance */
#define CRASH_PITCH -45.0f
@ -33,16 +32,13 @@
#define MAX_HERRING_EATEN 20
class Moveable
class Moveable : public UserPointer
{
public:
enum MoveableType {MOV_KART, MOV_PROJECTILE, MOV_TRACK} ;
private:
btVector3 m_velocityLC; /* velocity in kart coordinates */
protected:
MoveableType m_moveable_type; /* used when upcasting bullet user pointers */
sgCoord m_reset_pos; /* Where to start in case of a reset */
sgCoord m_curr_pos; /* current position */
sgCoord m_velocity; /* current velocity in local coordinates */
sgVec3 m_abs_velocity; /* world coordinates' velocity vector */
sgCoord m_reset_pos; /* Where to start in case of a reset */
sgCoord m_curr_pos; /* current position */
sgVec4* m_normal_hot; /* plane on which HOT was computed */
Material* m_material_hot; /* Material at HOT */
ssgTransform* m_model_transform; // The transform where the model is under
@ -68,25 +64,23 @@ public:
Moveable (bool bHasHistory=false);
virtual ~Moveable();
ssgTransform* getModelTransform() {return m_model_transform; }
MoveableType getMoveableType() const {return m_moveable_type; }
void setMoveableType(MoveableType m){m_moveable_type=m; }
sgCoord* getVelocity () {return & m_velocity; }
sgCoord* getCoord () {return &m_curr_pos; }
const sgCoord* getCoord () const {return &m_curr_pos; }
const sgVec4* getNormalHOT () const {return m_normal_hot; }
void setCoord (sgCoord* pos) {sgCopyCoord ( &m_curr_pos,pos); }
ssgTransform* getModelTransform() {return m_model_transform; }
const btVector3 &getVelocity() const {return m_body->getLinearVelocity();}
const btVector3 &getVelocityLC() const {return m_velocityLC; }
sgCoord* getCoord () {return &m_curr_pos; }
const sgCoord* getCoord () const {return &m_curr_pos; }
const sgVec4* getNormalHOT () const {return m_normal_hot; }
void setCoord (sgCoord* pos) {sgCopyCoord ( &m_curr_pos,pos); }
virtual void placeModel ();
virtual void handleZipper () {};
virtual void reset ();
virtual void update (float dt) ;
virtual void updatePosition(float dt, sgMat4 result);
void WriteHistory (char* s, int kartNumber, int indx);
void ReadHistory (char* s, int kartNumber, int indx);
btRigidBody* getBody () const {return m_body; }
void createBody(float mass, btTransform& trans,
btCollisionShape *shape, MoveableType m);
void getTrans (btTransform* t) const {*t=m_transform;}
btCollisionShape *shape,
UserPointer::UserPointerType t);
const btTransform& getTrans () const {return m_transform;}
void setTrans (btTransform& t){m_motion_state->setWorldTransform(t);}
}

View File

@ -103,18 +103,18 @@ void Physics::update(float dt)
std::vector<CollisionPair>::iterator p;
for(p=m_all_collisions.begin(); p!=m_all_collisions.end(); ++p)
{
if(p->type_a==Moveable::MOV_KART) { // kart-kart collision
if(p->type_a==UserPointer::UP_KART) { // kart-kart collision
Kart *kartA = (Kart*)(p->a);
Kart *kartB = (Kart*)(p->b);
KartKartCollision(kartA, kartB);
} // if kart-kart collision
else // now the first object must be a projectile
{
if(p->type_b==Moveable::MOV_TRACK) // must be projectile hit track
if(p->type_b==UserPointer::UP_TRACK) // must be projectile hit track
{
((Flyable*)(p->a))->hitTrack();
}
else if(p->type_b==Moveable::MOV_KART) // projectile hit kart
else if(p->type_b==UserPointer::UP_KART) // projectile hit kart
{
Flyable *f=(Flyable*)(p->a);
f->explode((Kart*)(p->b));
@ -206,60 +206,61 @@ btScalar Physics::solveGroup(btCollisionObject** bodies, int numBodies,
// =======================
if(!movA)
{
if(movB && movB->getMoveableType()==Moveable::MOV_PROJECTILE)
if(movB && movB->getUserPointerType()==UserPointer::UP_PROJECTILE)
{ // 1.1 projectile hits track
// -------------------------
m_all_collisions.push_back(CollisionPair(movB, Moveable::MOV_PROJECTILE,
NULL, Moveable::MOV_TRACK ));
m_all_collisions.push_back(CollisionPair(movB, UserPointer::UP_PROJECTILE,
NULL, UserPointer::UP_TRACK ));
}
else if(movB && movB->getMoveableType()==Moveable::MOV_KART)
else if(movB && movB->getUserPointerType()==UserPointer::UP_KART)
{
((Kart*)movB)->crashed();
}
}
// 2) object a is a kart
// =====================
else if(movA->getMoveableType()==Moveable::MOV_KART)
else if(movA->getUserPointerType()==UserPointer::UP_KART)
{
if(!movB)
{
{ // The casts here are important, otherwise re-casting the
// pointers later in kart-kart does not work as expected.
((Kart*)movA)->crashed();
}
else if(movB && movB->getMoveableType()==Moveable::MOV_PROJECTILE)
else if(movB && movB->getUserPointerType()==UserPointer::UP_PROJECTILE)
{ // 2.1 projectile hits kart
// -------------------------
m_all_collisions.push_back(CollisionPair(movB, Moveable::MOV_PROJECTILE,
movA, Moveable::MOV_KART ));
m_all_collisions.push_back(CollisionPair(movB, UserPointer::UP_PROJECTILE,
(Kart*)movA, UserPointer::UP_KART ));
}
else if(movB && movB->getMoveableType()==Moveable::MOV_KART)
else if(movB && movB->getUserPointerType()==UserPointer::UP_KART)
{ // 2.2 kart hits kart
// ------------------
m_all_collisions.push_back(CollisionPair(movA, Moveable::MOV_KART,
movB, Moveable::MOV_KART ));
m_all_collisions.push_back(CollisionPair((Kart*)movA, UserPointer::UP_KART,
(Kart*)movB, UserPointer::UP_KART ));
}
}
// 3) object is a projectile
// ========================
else if(movA->getMoveableType()==Moveable::MOV_PROJECTILE)
else if(movA->getUserPointerType()==UserPointer::UP_PROJECTILE)
{
if(!movB)
{ // 3.1) projectile hits track
// --------------------------
m_all_collisions.push_back(CollisionPair(movA, Moveable::MOV_PROJECTILE,
NULL, Moveable::MOV_TRACK ));
m_all_collisions.push_back(CollisionPair(movA, UserPointer::UP_PROJECTILE,
NULL, UserPointer::UP_TRACK ));
}
else if(movB->getMoveableType()==Moveable::MOV_PROJECTILE)
else if(movB->getUserPointerType()==UserPointer::UP_PROJECTILE)
{ // 3.2 projectile hits projectile
// ------------------------------
m_all_collisions.push_back(CollisionPair(movA, Moveable::MOV_PROJECTILE,
movB, Moveable::MOV_PROJECTILE));
m_all_collisions.push_back(CollisionPair(movA, UserPointer::UP_PROJECTILE,
movB, UserPointer::UP_PROJECTILE));
}
else if(movB->getMoveableType()==Moveable::MOV_KART)
else if(movB->getUserPointerType()==UserPointer::UP_KART)
{ // 3.3 projectile hits kart
// ------------------------
m_all_collisions.push_back(CollisionPair(movA, Moveable::MOV_PROJECTILE,
movB, Moveable::MOV_KART ));
m_all_collisions.push_back(CollisionPair(movA, UserPointer::UP_PROJECTILE,
(Kart*)movB, UserPointer::UP_KART ));
}
}
// 4) Nothing else should happen

View File

@ -51,13 +51,13 @@ private:
class CollisionPair {
public:
void *a, *b;
Moveable::MoveableType type_a, type_b;
UserPointer::UserPointerType type_a, type_b;
// The entries in Collision Pairs are sorted: if a projectile
// is included, it's always 'a'. If only two karts are reported
// the first kart pointer is the smaller one
CollisionPair(void *a1, Moveable::MoveableType atype,
void *b1, Moveable::MoveableType btype) {
if(atype==Moveable::MOV_KART && btype==Moveable::MOV_KART && a1>b1) {
CollisionPair(void *a1, UserPointer::UserPointerType atype,
void *b1, UserPointer::UserPointerType btype) {
if(atype==Moveable::UP_KART && btype==Moveable::UP_KART && a1>b1) {
a=b1;b=a1; type_a=btype; type_b=atype;
} else {
a=a1; b=b1; type_a=atype; type_b=btype;

View File

@ -223,7 +223,7 @@ void PlayerKart::addMessages()
// Display a warning message if the kart is going back way (unless
// the kart has already finished the race).
if ((angle_diff > 120.0f || angle_diff < -120.0f) &&
getVelocity () -> xyz [ 1 ] > 0.0 && !raceIsFinished() )
getVelocity().getY() > 0.0f && !raceIsFinished() )
{
m->addMessage(_("WRONG WAY!"), this, -1.0f, 60);
} // if angle is too big

View File

@ -133,7 +133,7 @@ void DefaultRobot::handle_braking()
//We may brake if we are about to get out of the road, but only if the
//kart is on top of the road, and if we won't slow down below a certain
//limit.
if ( m_crashes.m_road && m_on_road && m_velocity.xyz[1] > MIN_SPEED)
if ( m_crashes.m_road && m_on_road && getVelocityLC().getY() > MIN_SPEED)
{
float kart_ang_diff = world->m_track->m_angle[m_track_sector] -
m_curr_pos.hpr[0];
@ -172,7 +172,7 @@ void DefaultRobot::handle_braking()
//Brake if the kart's speed is bigger than the speed we need
//to go through the curve at the widest angle, or if the kart
//is not going straight in relation to the road.
if(m_velocity.xyz[1] > m_curve_target_speed ||
if(getVelocityLC().getY() > m_curve_target_speed ||
kart_ang_diff > MIN_TRACK_ANGLE )
{
#ifdef AI_DEBUG
@ -407,14 +407,16 @@ bool DefaultRobot::do_wheelie ( const int STEPS )
if( m_crashes.m_road ) return false;
if( m_crashes.m_kart != -1 ) return false;
sgVec2 vel_normal, step_coord;
sgVec2 step_coord;
sgVec3 step_track_coord;
float distance;
//We have to be careful with normalizing, because if the source argument
//has both the X and Y axis set to 0, it returns nan to the destiny.
if( m_abs_velocity[0] == 0.0 && m_abs_velocity[1] == 0.0 ) return false;
sgNormalizeVec2( vel_normal, m_abs_velocity );
const btVector3 &VEL=getVelocity();
if( VEL.getX() == 0.0 && VEL.getY() == 0.0 ) return false;
btVector3 vel_normal(VEL.getX(), VEL.getY(), 0.0);
vel_normal.normalize();
//FIXME: instead of using 1.5, it should find out how much time it
//will pass to stop doing the wheelie completely from the current state.
@ -423,7 +425,7 @@ bool DefaultRobot::do_wheelie ( const int STEPS )
/* The following method of finding if a position is outside of the track
is less accurate than calling findRoadSector(), but a lot faster.
*/
const int WHEELIE_STEPS = int(( m_velocity.xyz[1] * CHECK_DIST )/
const int WHEELIE_STEPS = int(( getVelocityLC().getY() * CHECK_DIST )/
m_kart_properties->getKartLength() );
for( int i = WHEELIE_STEPS; i > STEPS - 1; --i )
@ -527,7 +529,7 @@ void DefaultRobot::check_crashes( const int STEPS, sgVec3 const pos )
//having karts too close in any direction. The crash with the track can
//tell when a kart is going to get out of the track so it steers.
sgVec2 vel_normal;
btVector3 vel_normal;
//in this func we use it as a 2d-vector, but later on it is passed
//to world->m_track->findRoadSector, there it is used as a 3d-vector
//to find distance to plane, so z must be initialized to zero
@ -541,11 +543,16 @@ void DefaultRobot::check_crashes( const int STEPS, sgVec3 const pos )
const size_t NUM_KARTS = world->getNumKarts();
//Protection against having vel_normal with nan values
if( m_abs_velocity[0] == 0.0 && m_abs_velocity[1] == 0.0 )
const btVector3 &VEL = getVelocity();
if( VEL.getX() == 0.0 && VEL.getY() == 0.0 )
{
vel_normal[0] = vel_normal[1] = 0.0;
vel_normal.setValue(0.0, 0.0, 0.0);
}
else
{
vel_normal.setValue(VEL.getX(), VEL.getY(), 0.0);
vel_normal.normalize();
}
else sgNormalizeVec2( vel_normal, m_abs_velocity );
for(int i = 1; STEPS > i; ++i)
{
@ -564,8 +571,8 @@ void DefaultRobot::check_crashes( const int STEPS, sgVec3 const pos )
world->getKart(j)->getCoord()->xyz );
if( kart_distance < m_kart_properties->getKartLength() + 0.125f * i )
if( m_velocity.xyz[1] > world->getKart(j)->
getVelocity()->xyz[1] * 0.75f ) m_crashes.m_kart = j;
if( getVelocityLC().getY() > world->getKart(j)->
getVelocityLC().getY() * 0.75f ) m_crashes.m_kart = j;
}
}
@ -751,7 +758,7 @@ inline float DefaultRobot::normalize_angle( float angle )
*/
int DefaultRobot::calc_steps()
{
int steps = int( m_velocity.xyz[1] / m_kart_properties->getKartLength() );
int steps = int( getVelocityLC().getY() / m_kart_properties->getKartLength() );
if( steps < m_min_steps ) steps = m_min_steps;
//Increase the steps depending on the width, if we steering hard,
@ -869,7 +876,7 @@ void DefaultRobot::find_curve()
int next_hint = m_track_sector;
int i;
for(i = m_track_sector; total_dist < m_velocity.xyz[1]; i = next_hint)
for(i = m_track_sector; total_dist < getVelocityLC().getY(); i = next_hint)
{
next_hint = i + 1 < DRIVELINE_SIZE ? i + 1 : 0;
total_dist += sgDistanceVec2(world->m_track->m_driveline[i], world->m_track->m_driveline[next_hint]);

View File

@ -66,13 +66,14 @@ SoundManager::SoundManager()
else
m_initialized = true;
#else
if(alutInit(0, NULL) == AL_TRUE) // init OpenAL sound system
m_initialized = true;
else
{
fprintf(stderr, _("WARNING: Could not initialize the ALUT based sound.\n"));
m_initialized = false;
}
// if(alutInit(0, NULL) == AL_TRUE) // init OpenAL sound system
alutInit(0, NULL);
// m_initialized = true;
// else
// {
// fprintf(stderr, _("WARNING: Could not initialize the ALUT based sound.\n"));
// m_initialized = false;
// }
alGetError(); //Called here to clear any non-important errors found
#endif
@ -187,7 +188,7 @@ void SoundManager::playMusic(const char* filename)
if((m_current_music->load(filename)) == false)
{
delete m_current_music;
m_current_music=0;
m_current_music=0;
fprintf(stderr, "WARNING: Unabled to load music %s, not supported or not found.\n", filename);
}
else

View File

@ -34,7 +34,6 @@ void STKConfig::load(const std::string filename)
fprintf(stderr,"Missing default value for '%s' in '%s'.\n", \
strA,filename.c_str());exit(-1); \
}
#ifdef BULLET
if(m_gear_switch_ratio.size()==0)
{
fprintf(stderr,"Missing default value for 'gear-switch-ratio' in '%s'.\n",
@ -52,7 +51,7 @@ void STKConfig::load(const std::string filename)
fprintf(stderr,"in '%s' must be equal.\n", filename.c_str());
exit(-1);
}
#endif
CHECK_NEG(m_max_karts, "max-karts" );
CHECK_NEG(m_grid_order, "grid-order" );
@ -109,6 +108,8 @@ void STKConfig::load(const std::string filename)
CHECK_NEG(m_bomb_time, "bomb-time" );
CHECK_NEG(m_bomb_time_increase, "bomb-time-increase" );
CHECK_NEG(m_anvil_time, "anvil-time" );
CHECK_NEG(m_zipper_time, "zipper-time" );
CHECK_NEG(m_zipper_force, "zipper-force" );
CHECK_NEG(m_max_road_distance, "shortcut-road-distance" );
CHECK_NEG(m_shortcut_segments, "shortcut-skipped-segments" );
CHECK_NEG(m_suspension_rest, "suspension-rest" );
@ -134,6 +135,7 @@ void STKConfig::init_defaults()
m_wheelie_max_speed_ratio = m_wheelie_pitch_rate = m_wheelie_restore_rate =
m_wheelie_speed_boost = m_air_res_reduce[2] = m_air_res_reduce[1] =
m_parachute_time = m_bomb_time = m_bomb_time_increase= m_anvil_time =
m_zipper_time = m_zipper_force =
m_parachute_time_other = m_magnet_time = m_max_road_distance = m_shortcut_segments =
//bullet physics data
m_suspension_stiffness = m_wheel_damping_relaxation = m_wheel_damping_compression =
@ -170,6 +172,8 @@ void STKConfig::getAllData(const lisp::Lisp* lisp)
lisp->get("bomb-time", m_bomb_time );
lisp->get("bomb-time-increase", m_bomb_time_increase );
lisp->get("anvil-time", m_anvil_time );
lisp->get("zipper-time", m_zipper_time );
lisp->get("zipper-force", m_zipper_force );
lisp->get("explosion-impulse", m_explosion_impulse );
lisp->get("max-karts", m_max_karts );
lisp->get("grid-order", m_grid_order );

View File

@ -39,6 +39,8 @@ public:
float m_bomb_time; // time before a bomb explodes
float m_bomb_time_increase; // time added to bomb timer when it's passed on
float m_anvil_time; // time an anvil is active
float m_zipper_time; // duration a zipper is active
float m_zipper_force; // additional force added to the acceleration
float m_max_road_distance; // max distance from road to be still ON road
float m_shortcut_segments; // skipping more than this number of segments is
// considered to be a shortcut

View File

@ -41,7 +41,6 @@
#if defined(WIN32) && !defined(__CYGWIN__)
# define snprintf _snprintf
#endif
std::vector<const Material*>Track::m_triangleIndex2Material;
float const Track::NOHIT=-99999.9f;
@ -72,8 +71,8 @@ Track::~Track()
*/
void Track::cleanup()
{
world->getPhysics()->removeBody(m_body);
delete m_body;
delete m_non_collision_mesh;
delete m_track_mesh;
} // ~Track
//-----------------------------------------------------------------------------
@ -1007,29 +1006,22 @@ Track::readDrivelineFromFile(std::vector<sgVec3Wrapper>& line, const std::string
void Track::createPhysicsModel()
{
if(!m_model) return;
m_track_mesh = new TriangleMesh();
m_non_collision_mesh = new TriangleMesh();
// Collect all triangles in the track_mesh
sgMat4 mat;
sgMakeIdentMat4(mat);
btTriangleMesh *track_mesh = new btTriangleMesh();
m_triangleIndex2Material.clear();
// Collect all triangles in the track_mesh
convertTrackToBullet(m_model, mat, track_mesh);
convertTrackToBullet(m_model, mat);
m_track_mesh->createBody();
m_non_collision_mesh->createBody(btCollisionObject::CF_NO_CONTACT_RESPONSE);
// Now convert the triangle mesh into a static rigid body
btCollisionShape *mesh_shape = new btBvhTriangleMeshShape(track_mesh, true);
btTransform startTransform;
startTransform.setIdentity();
btDefaultMotionState *myMotionState = new btDefaultMotionState(startTransform);
m_body=new btRigidBody(0.0f, myMotionState, mesh_shape);
// FIXME: can the mesh_shape and or track_mesh be deleted now?
world->getPhysics()->addBody(m_body);
m_body->setUserPointer(0);
m_body->setCollisionFlags(m_body->getCollisionFlags() |
btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK);
} // createPhysicsModel
// -----------------------------------------------------------------------------
//* Convert the ssg track tree into its physics equivalents.
void Track::convertTrackToBullet(ssgEntity *track, sgMat4 m, btTriangleMesh* track_mesh)
void Track::convertTrackToBullet(ssgEntity *track, sgMat4 m)
{
if(!track) return;
MovingPhysics *mp = dynamic_cast<MovingPhysics*>(track);
@ -1042,10 +1034,10 @@ void Track::convertTrackToBullet(ssgEntity *track, sgMat4 m, btTriangleMesh* tra
}
else if(track->isAKindOf(ssgTypeLeaf()))
{
ssgLeaf *leaf = (ssgLeaf*)(track);
Material *mat = material_manager->getMaterial(leaf);
ssgLeaf *leaf = (ssgLeaf*)(track);
Material *material = material_manager->getMaterial(leaf);
// Don't convert triangles with material that is ignored (e.g. fuzzy_sand)
if(!mat || mat->isIgnore()) return;
if(!material || material->isIgnore()) return;
for(int i=0; i<leaf->getNumTriangles(); i++)
{
@ -1059,8 +1051,14 @@ void Track::convertTrackToBullet(ssgEntity *track, sgMat4 m, btTriangleMesh* tra
btVector3 vb1(vv1[0],vv1[1],vv1[2]);
btVector3 vb2(vv2[0],vv2[1],vv2[2]);
btVector3 vb3(vv3[0],vv3[1],vv3[2]);
track_mesh->addTriangle(vb1, vb2, vb3);
m_triangleIndex2Material.push_back(mat);
if(material->isZipper())
{
m_non_collision_mesh->addTriangle(vb1, vb2, vb3, material);
}
else
{
m_track_mesh->addTriangle(vb1, vb2, vb3, material);
}
}
} // if(track isAKindOf leaf)
@ -1073,14 +1071,14 @@ void Track::convertTrackToBullet(ssgEntity *track, sgMat4 m, btTriangleMesh* tra
sgPreMultMat4(tmpM,tmpT);
for(ssgEntity *e = t->getKid(0); e!=NULL; e=t->getNextKid())
{
convertTrackToBullet(e, tmpM, track_mesh);
convertTrackToBullet(e, tmpM);
} // for i
}
else if (track->isAKindOf(ssgTypeBranch()))
{
ssgBranch *b =(ssgBranch*)track;
for(ssgEntity* e=b->getKid(0); e!=NULL; e=b->getNextKid()) {
convertTrackToBullet(e, m, track_mesh);
convertTrackToBullet(e, m);
} // for i<getNumKids
}
else
@ -1161,7 +1159,7 @@ void Track::loadTrackModel()
}
else if ( sscanf ( s, "\"%[^\"]\",%f,%f,{},%f,{},{}",
fname, &(loc.xyz[0]), &(loc.xyz[1]),
&(loc.hpr[0]) ) == 3 )
&(loc.hpr[0]) ) == 4 )
{
/* All 6 DOF specified - but need height, roll, pitch */
need_hat = true ;
@ -1291,7 +1289,7 @@ void Track::getTerrainInfo(btVector3 &pos, float *hot, btVector3* normal,
bool normalInWorldSpace) {
if(rayResult.m_localShapeInfo && rayResult.m_localShapeInfo->m_shapePart>=0 )
{
m_material=m_triangleIndex2Material[rayResult.m_localShapeInfo->m_triangleIndex];
m_material = ((TriangleMesh*)rayResult.m_collisionObject->getUserPointer())->getMaterial(rayResult.m_localShapeInfo->m_triangleIndex);
}
return btCollisionWorld::ClosestRayResultCallback::AddSingleResult(rayResult,
normalInWorldSpace);

View File

@ -35,6 +35,7 @@
#include <vector>
#include "btBulletDynamicsCommon.h"
#include "material.hpp"
#include "triangle_mesh.hpp"
class Track
{
@ -49,8 +50,8 @@ private:
std::string m_description;
std::string m_filename;
ssgBranch* m_model;
btRigidBody* m_body;
static std::vector<const Material*> m_triangleIndex2Material;
TriangleMesh* m_track_mesh;
TriangleMesh* m_non_collision_mesh;
public:
enum RoadSide{ RS_DONT_KNOW = -1, RS_LEFT = 0, RS_RIGHT = 1 };
@ -182,7 +183,7 @@ public:
const std::vector<SGfloat>& getWidth() const {return m_path_width; }
const std::string& getHerringStyle () const {return m_herring_style; }
void getStartCoords (unsigned int pos, sgCoord* coords) const;
static const Material* getMaterial (unsigned int n) {return m_triangleIndex2Material[n];}
// static const Material* getMaterial (unsigned int n) {return m_triangleIndex2Material[n];}
void getTerrainInfo(btVector3 &pos, float *hot, btVector3* normal,
const Material **material) const;
void createPhysicsModel ();
@ -194,18 +195,17 @@ public:
}
private:
void loadTrack (std::string filename);
void herring_command (sgVec3 *xyz, char htype, int bNeedHeight);
void loadDriveline ();
void readDrivelineFromFile (std::vector<sgVec3Wrapper>& line,
void loadTrack (std::string filename);
void herring_command (sgVec3 *xyz, char htype, int bNeedHeight);
void loadDriveline ();
void readDrivelineFromFile (std::vector<sgVec3Wrapper>& line,
const std::string& file_ext );
void convertTrackToBullet (ssgEntity *track, sgMat4 m,
btTriangleMesh* track_mesh);
void convertTrackToBullet (ssgEntity *track, sgMat4 m);
float pointSideToLine( const sgVec2 L1, const sgVec2 L2,
const sgVec2 P ) const;
int pointInQuad( const sgVec2 A, const sgVec2 B,
const sgVec2 C, const sgVec2 D, const sgVec2 POINT ) const;
float pointSideToLine(const sgVec2 L1, const sgVec2 L2,
const sgVec2 P ) const;
int pointInQuad(const sgVec2 A, const sgVec2 B,
const sgVec2 C, const sgVec2 D, const sgVec2 POINT ) const;
}
; // class Track

View File

@ -36,12 +36,12 @@ void TrafficDriver::update (float dt)
if ( ( track_velocity [ 0 ] < 0.0f && m_curr_track_coords [ 0 ] > 0.0f ) ||
( track_velocity [ 0 ] > 0.0f && m_curr_track_coords [ 0 ] < 0.0f ) )
m_velocity.hpr[0] = sgnsq(m_curr_track_coords[0])*3.0f ;
;//FIXME m_velocity.hpr[0] = sgnsq(m_curr_track_coords[0])*3.0f ;
else
m_velocity.hpr[0] = sgnsq(m_curr_track_coords[0])*12.0f ;
//FIXME m_velocity.hpr[0] = sgnsq(m_curr_track_coords[0])*12.0f ;
m_velocity.xyz[1] = TRAFFIC_VELOCITY ;
m_velocity.xyz[2] -= world->getGravity()* dt ;
//FIXME m_velocity.xyz[1] = TRAFFIC_VELOCITY ;
//FIXME m_velocity.xyz[2] -= world->getGravity()* dt ;
if ( m_wheelie_angle != 0.0f )
m_wheelie_angle = 0.0f ;

67
src/triangle_mesh.cpp Normal file
View File

@ -0,0 +1,67 @@
// $Id: triangle_mesh.cpp 839 2006-10-24 00:01:56Z hiker $
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2006 Joerg Henrichs
//
// 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 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty ofati
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "triangle_mesh.hpp"
#include "world.hpp"
// -----------------------------------------------------------------------------
TriangleMesh::~TriangleMesh()
{
if(m_body)
{
world->getPhysics()->removeBody(m_body);
delete m_body;
delete m_motion_state;
delete m_collision_shape;
}
} // ~TriangleMesh
// -----------------------------------------------------------------------------
void TriangleMesh::addTriangle(btVector3 t1, btVector3 t2, btVector3 t3,
const Material* m)
{
m_triangleIndex2Material.push_back(m);
m_mesh.addTriangle(t1, t2, t3);
} // addTriangle
// -----------------------------------------------------------------------------
void TriangleMesh::createBody(btCollisionObject::CollisionFlags flags)
{
if(m_triangleIndex2Material.size()==0)
{
m_collision_shape = NULL;
m_motion_state = NULL;
m_body = NULL;
return;
}
// Now convert the triangle mesh into a static rigid body
m_collision_shape = new btBvhTriangleMeshShape(&m_mesh, true);
btTransform startTransform;
startTransform.setIdentity();
m_motion_state = new btDefaultMotionState(startTransform);
m_body=new btRigidBody(0.0f, m_motion_state, m_collision_shape);
world->getPhysics()->addBody(m_body);
m_body->setUserPointer(this);
m_body->setCollisionFlags(m_body->getCollisionFlags() |
flags |
btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK);
} // createBody
// -----------------------------------------------------------------------------

49
src/triangle_mesh.hpp Normal file
View File

@ -0,0 +1,49 @@
// $Id: triangle_mesh.hpp 839 2006-10-24 00:01:56Z hiker $
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2006 Joerg Henrichs
//
// 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 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef HEADER_TRIANGLE_MESH_H
#define HEADER_TRIANGLE_MESH_H
#include <vector>
#include "user_pointer.hpp"
#include "btBulletDynamicsCommon.h"
#include "material.hpp"
/** A special class to store a triangle mesh with a separate material
* per triangle.
*/
class TriangleMesh : public UserPointer
{
std::vector<const Material*> m_triangleIndex2Material;
btRigidBody *m_body;
btTriangleMesh m_mesh;
btDefaultMotionState *m_motion_state;
btCollisionShape *m_collision_shape;
public:
TriangleMesh(): UserPointer(UserPointer::UP_TRACK), m_mesh() {};
~TriangleMesh();
void addTriangle(btVector3 t1, btVector3 t2, btVector3 t3,
const Material* m);
void createBody(btCollisionObject::CollisionFlags flags=
(btCollisionObject::CollisionFlags)0);
const Material* getMaterial(int n) const {return m_triangleIndex2Material[n];}
};
#endif
/* EOF */

41
src/user_pointer.hpp Normal file
View File

@ -0,0 +1,41 @@
// $Id: user_pointer.hpp 839 2006-10-24 00:01:56Z hiker $
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2007 Joerg Henrichs
//
// 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 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef HEADER_USER_POINTER_H
#define HEADER_USER_POINTER_H
/** Some bullet objects store 'user pointers'. This is a base class
* that allows to easily determine the type of the user pointer.
*/
class UserPointer
{
public:
enum UserPointerType {UP_UNDEF, UP_KART, UP_PROJECTILE, UP_TRACK} ;
protected:
UserPointerType m_user_pointer_type;
public:
UserPointerType getUserPointerType() const {return m_user_pointer_type;}
void setUserPointerType(UserPointerType t)
{ m_user_pointer_type=t; }
UserPointer(): m_user_pointer_type(UP_UNDEF) {};
UserPointer(UserPointerType t): m_user_pointer_type(t) {};
};
#endif
/* EOF */