1) Improved rockets and sparks for bullet physics

Parameters for rockets etc. can for now be
   set in data/*.projectile
2) Fixed bugs causing rockets not to explode (and
   potentialy start rotating)
3) Added (somewhat temporarily) some cheats to get
   rockets, homing missiles and sparks as F1/2/3
4) Fixed several memory leaks.
5) Fixed (very rare) occurring crash when deleting
   phsyics.
6) Started to remove non-bullet physics code
7) Bullet physics is now the default, and it
   can not be disabled anymore!!
Important note: 
From this revision on, non-bullet physics is NOT
supported anymore, and will (most likely) not
compile. For now a -DBULLET is still necessary (it
is added as default), but the code will be cleaned
up in the near future.


git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/trunk/supertuxkart@1325 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hikerstk 2007-12-08 13:04:56 +00:00
parent 12cee75a0f
commit 7ed846ca3e
44 changed files with 504 additions and 670 deletions

View File

@ -1,16 +1,17 @@
Preliminary support for the bullet physics engine has been
added, and bullet itself is part of the STK sources by noq.
To enable it, use the '--enable-bullet' option in configure,
that should be all (though up to now only linux and cygwin
have been tested with the new, integrated bullet version).
Beginning with revision r1325 bullet physics is being used
in SuperTuxKart. A copy of bullet is included in
the sources and the STK build environment, so it's
not necessary to install your own version.
Even though we officiall switched to bullet physics,
not all 'old' features of STK are fully supported yet.
For now mainly the race track works as expected, all tracks
can be played (though the performance in some tracks is somewhat
bad at the moment). Most important bugs:
can be played. Most important bugs:
- not all collectable work
(zippers don't work, homing missiles don't go to the target,
sparks won't fly as expected either), but collision with
karts work.
(zippers don't do much at the moment, rockets and sparks mostly
work, but are sometimes too high)
- karts are not automatically rescued when touching
water or lava
- no proper friction handling, so no skidding
(though skidding potentially works - if the friction is
set correctly).
@ -19,8 +20,6 @@ bad at the moment). Most important bugs:
- rescuing an upside-down kart will return the kart to the middle
of the track (waypoints) - the kart should be returned to where
it ended, just with a proper orientation.
- if a kart is upside down, it will actually hang under the
track.
- tuxtrack is using real rigid bodies for the roadcone and roadblock,
so they are pushed around when hit by a kart. Currently, the
start orientation is not used, so the heading of the objects

View File

@ -32,11 +32,12 @@ Comments:
Visual C++ Express
==================
There are now project files included for building SuperTuxKart with
Visual C++ - have a look at the src/ide/vc8 folder.
Since version r793 SuperTuxKart compiles with Visual C++ Express,
version 8.0, since rev 1267 Visual C++ project files are included.
The main project file is .../src/ide/vc8/supertuxkart.vcproj,
and it include a sub project for the bullet library. More details
and it includes a sub project for the bullet library. More details
can be found in .../src/ide/vc8/README.
You still have to install all dependencies, and:

View File

@ -347,34 +347,20 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM()],
CXXFLAGS="$ORIGCXXFLAGS"
AC_SUBST(NOREGMOVE)
dnl =======================================
dnl Bullet physics - currently experimental
dnl =======================================
dnl Check for bullet physics. Currently, this is optional and needs
dnl a '--enable-bullet' during configure to be used.
AC_MSG_CHECKING(for bullet physics)
AC_ARG_ENABLE(bullet,
AC_HELP_STRING([--enable-bullet], [enable bullet physics]),
[enable_bullet="$enableval"],
[enable_bullet="no"])
if test "x${enable_bullet}" != "xno"; then
AC_DEFINE([BULLET], [], [Use the bullet physics engine])
AC_MSG_RESULT([enabled])
CXXFLAGS="$CXXFLAGS -Ibullet/src"
AC_CONFIG_FILES([ \
dnl ==============
dnl Bullet physics
dnl ==============
AC_DEFINE([BULLET], [], [Use the bullet physics engine])
CXXFLAGS="$CXXFLAGS -Ibullet/src"
AC_CONFIG_FILES([ \
src/bullet/Makefile \
src/bullet/src/Makefile \
src/bullet/Demos/OpenGL/Makefile
])
SUMMARY="$SUMMARY\nUsing bullet physics."
BULLETTREE="src/bullet"
bullet_LIBS="-L bullet/Demos/OpenGL -lbulletopenglsupport -L bullet/src -lbulletdynamics -lbulletcollision -lbulletmath -lglut"
else
AC_MSG_RESULT([disabled])
BULLETTREE=""
bullet_LIBS=""
])
SUMMARY="$SUMMARY\nUsing bullet physics."
BULLETTREE="src/bullet"
bullet_LIBS="-L bullet/Demos/OpenGL -lbulletopenglsupport -L bullet/src -lbulletdynamics -lbulletcollision -lbulletmath -lglut"
fi
AC_SUBST(BULLETTREE)
dnl ================

View File

@ -4,7 +4,12 @@
(name "homing")
(model "homingmissile.ac")
(icon "homingmissile.rgb")
(speed 25.0)
(speed 35.0)
(min-height 0.2)
(max-height 1.0)
(max-distance 20.0) ;; maximum distance at which a kart is still followed
(max-turn-angle 5.0) ;; maximum turn angle when following a kart
(force-updown 25.0) ;; force raising/lowering the homing missile if it's too low/high
)
;; EOF ;;

View File

@ -5,6 +5,9 @@
(model "missile.ac")
(icon "missile.rgb")
(speed 50.0)
(min-height 0.2)
(max-height 1.0)
(force-updown 15.0)
)
;; EOF ;;

View File

@ -5,6 +5,16 @@
(model "spark.ac")
(icon "spark.rgb")
(speed 5.0)
(min-height 0.2) ; height above terrain below which a spark is
; started to be pulled up
(max-height 3.0) ; height above terrain at which a spark is
; started to be pulled back to ground
(force-updown 20.0) ; force pushing the spark down
; when it's too high above ground
(force-to-target 20) ; force with which a spark flies towards
; the nearest kart
(max-distance 10) ; maximum distance the spark can be away
; from a kart when accelerating towards it
)
;; EOF ;;

View File

@ -38,7 +38,6 @@ supertuxkart_SOURCES = main.cpp \
music_mikmod.cpp music_mikmod.hpp \
music_ogg.cpp music_ogg.hpp \
sfx_openal.cpp sfx_openal.hpp \
utils.cpp utils.hpp \
input.hpp \
isect.cpp isect.hpp \
track.cpp track.hpp \
@ -77,7 +76,10 @@ supertuxkart_SOURCES = main.cpp \
kart.cpp kart.hpp \
auto_kart.hpp \
player_kart.cpp player_kart.hpp \
projectile.cpp projectile.hpp \
flyable.cpp flyable.hpp \
missile.cpp missile.hpp \
homing.cpp homing.hpp \
spark.cpp spark.hpp \
history.cpp history.hpp \
scene.hpp scene.cpp \
race_setup.hpp no_copy.hpp \

View File

@ -36,7 +36,7 @@ Attachment::Attachment(Kart* _kart)
m_kart = _kart;
m_holder = new ssgSelector();
m_previous_owner = NULL;
m_kart->getModel()->addKid(m_holder);
m_kart->getModelTransform()->addKid(m_holder);
for(int i=ATTACH_PARACHUTE; i<=ATTACH_TINYTUX; i++)
{

View File

@ -58,6 +58,7 @@ public:
}
attachmentType getType () const { return m_type; }
float getTimeLeft () const { return m_time_left; }
void setTimeLeft (float t){ m_time_left = t; }
Kart* getPreviousOwner () const { return m_previous_owner; }
float WeightAdjust () const {
return m_type==ATTACH_ANVIL

View File

@ -18,6 +18,7 @@
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "callback_manager.hpp"
#include "moving_physics.hpp"
CallbackManager *callback_manager=NULL;

View File

@ -28,21 +28,21 @@
//-----------------------------------------------------------------------------
Collectable::Collectable(Kart* kart_)
{
owner = kart_;
type = COLLECT_NOTHING;
number = 0;
m_owner = kart_;
m_type = COLLECT_NOTHING;
m_number = 0;
} // Collectable
//-----------------------------------------------------------------------------
void Collectable::set(collectableType _type, int n)
void Collectable::set(CollectableType type, int n)
{
if (type==_type)
if (m_type==type)
{
number+=n;
m_number+=n;
return;
}
type=_type;
number=n;
m_type=type;
m_number=n;
} // set
//-----------------------------------------------------------------------------
@ -50,7 +50,7 @@ Material *Collectable::getIcon()
{
// Check if it's one of the types which have a separate
// data file which includes the icon:
return collectable_manager->getIcon(type);
return collectable_manager->getIcon(m_type);
}
//-----------------------------------------------------------------------------
@ -70,22 +70,22 @@ void Collectable::use()
} // if MAGNET_BZZT
} // user_config->disableMagnet
#endif
number--;
switch (type)
m_number--;
switch (m_type)
{
#ifdef USE_MAGNET
case COLLECT_MAGNET: owner->attach(ATTACH_MAGNET_BZZT, stk_config->m_magnet_time);
case COLLECT_MAGNET: m_owner->attach(ATTACH_MAGNET_BZZT, stk_config->m_magnet_time);
break ;
#endif
case COLLECT_ZIPPER: owner->handleZipper();
case COLLECT_ZIPPER: m_owner->handleZipper();
break ;
case COLLECT_HOMING_MISSILE:
case COLLECT_HOMING:
case COLLECT_SPARK:
case COLLECT_MISSILE:
if(owner->isPlayerKart())
if(m_owner->isPlayerKart())
sound_manager->playSfx(SOUND_SHOT);
projectile_manager->newProjectile(owner, type);
projectile_manager->newProjectile(m_owner, m_type);
break ;
case COLLECT_ANVIL:
@ -93,7 +93,7 @@ void Collectable::use()
//by the bananas) to the kart in the 1st position.
for(unsigned int i = 0 ; i < world->getNumKarts(); ++i)
{
if(world->getKart(i) == owner) continue;
if(world->getKart(i) == m_owner) continue;
if(world->getKart(i)->getPosition() == 1)
{
world->getKart(i)->
@ -117,8 +117,8 @@ void Collectable::use()
//are in front of this one.
for(unsigned int i = 0 ; i < world->getNumKarts(); ++i)
{
if(world->getKart(i) == owner) continue;
if(owner->getPosition() > world->
if(world->getKart(i) == m_owner) continue;
if(m_owner->getPosition() > world->
getKart(i)->getPosition())
{
world->getKart(i)->attach(
@ -139,7 +139,7 @@ void Collectable::use()
default : break ;
}
if ( number <= 0 )
if ( m_number <= 0 )
{
clear();
}
@ -152,10 +152,10 @@ void Collectable::hitRedHerring(int n)
//depending on how bad the owner's position is. For the first
//driver the posibility is none, for the last player is 15 %.
if(owner->getPosition() != 1 && type == COLLECT_NOTHING)
if(m_owner->getPosition() != 1 && m_type == COLLECT_NOTHING)
{
const int SPECIAL_PROB = (int)(15.0 / ((float)world->getNumKarts() /
(float)owner->getPosition()));
(float)m_owner->getPosition()));
const int RAND_NUM = rand()%100;
if(RAND_NUM <= SPECIAL_PROB)
{
@ -163,18 +163,18 @@ void Collectable::hitRedHerring(int n)
//the parachute.
for(unsigned int i=0; i < world->getNumKarts(); ++i)
{
if(world->getKart(i) == owner) continue;
if(world->getKart(i) == m_owner) continue;
if(world->getKart(i)->getPosition() == 1 && world->getKart(i)->
raceIsFinished())
{
type = COLLECT_PARACHUTE;
number = 1;
m_type = COLLECT_PARACHUTE;
m_number = 1;
return;
}
}
type = rand()%(2) == 0 ? COLLECT_ANVIL : COLLECT_PARACHUTE;
number = 1;
m_type = rand()%(2) == 0 ? COLLECT_ANVIL : COLLECT_PARACHUTE;
m_number = 1;
return;
}
}
@ -182,7 +182,7 @@ void Collectable::hitRedHerring(int n)
//rand() is moduled by COLLECT_MAX - 1 - 2 because because we have to
//exclude the anvil and the parachute, but later we have to add 1 to prevent
//having a value of 0 since that isn't a valid collectable.
collectableType newC;
CollectableType newC;
if(!user_config->m_profile)
{
// A zipper should not be used during time trial, since it
@ -190,24 +190,24 @@ void Collectable::hitRedHerring(int n)
// in time trail, but only the top 2 in any other mode
int nIgnore = (world->m_race_setup.m_mode == RaceSetup::RM_TIME_TRIAL)
? 3 : 2;
newC = (collectableType)(rand()%(COLLECT_MAX - 1 - nIgnore) + 1);
newC = (CollectableType)(rand()%(COLLECT_MAX - 1 - nIgnore) + 1);
}
else
{
// No random effects when profiling!
static int simpleCounter=-1;
simpleCounter++;
newC = (collectableType)(simpleCounter%(COLLECT_MAX - 1 - 2) + 1);
newC = (CollectableType)(simpleCounter%(COLLECT_MAX - 1 - 2) + 1);
}
if(type==COLLECT_NOTHING)
if(m_type==COLLECT_NOTHING)
{
type=newC;
number = n;
m_type=newC;
m_number = n;
}
else if(newC==type)
else if(newC==m_type)
{
number+=n;
if(number > MAX_COLLECTABLES) number = MAX_COLLECTABLES;
m_number+=n;
if(m_number > MAX_COLLECTABLES) m_number = MAX_COLLECTABLES;
}
// Ignore new collectable if it is different from the current one
} // hitRedHerring

View File

@ -29,16 +29,16 @@ class Kart;
class Collectable
{
protected:
Kart* owner;
collectableType type;
int number;
Kart* m_owner;
CollectableType m_type;
int m_number;
public:
Collectable (Kart* kart_);
void set (collectableType _type, int n=1);
void clear () {type=COLLECT_NOTHING; number=0;}
int getNum () const {return number;}
collectableType getType () {return type;}
void set (CollectableType _type, int n=1);
void clear () {m_type=COLLECT_NOTHING; m_number=0;}
int getNum () const {return m_number;}
CollectableType getType () {return m_type;}
void hitRedHerring(int n);
Material* getIcon ();
void use ();

View File

@ -24,13 +24,16 @@
#include "material_manager.hpp"
#include "material.hpp"
#include "translation.hpp"
#include "spark.hpp"
#include "missile.hpp"
#include "homing.hpp"
#if defined(WIN32) && !defined(__CYGWIN__)
# define snprintf _snprintf
#endif
typedef struct
{
collectableType collectable;
CollectableType collectable;
const char*const dataFile;
}
initCollectableType;
@ -43,7 +46,7 @@ initCollectableType ict[]=
#endif
{COLLECT_SPARK, "spark.projectile" },
{COLLECT_MISSILE, "missile.projectile" },
{COLLECT_HOMING_MISSILE, "homingmissile.projectile" },
{COLLECT_HOMING, "homingmissile.projectile" },
{COLLECT_ANVIL, "anvil.collectable" },
{COLLECT_PARACHUTE, "parachute.collectable" },
{COLLECT_MAX, "" },
@ -110,22 +113,12 @@ void CollectableManager::Load(int collectType, const char* filename)
void CollectableManager::LoadNode(const lisp::Lisp* lisp, int collectType )
{
std::string sName, sModel, sIconFile;
int dummy;
lisp->get("name", sName ); // the name is actually ignored
lisp->get("name", sName );
lisp->get("model", sModel );
lisp->get("icon", sIconFile );
// If the speed value is an integer (e.g. no "."), an uninitialised
// value will be returned. In this case try reading the speed as
// an integer value.
if(!lisp->get("speed", m_all_speeds[collectType]))
{
dummy=-1;
lisp->get("speed", dummy);
m_all_speeds[collectType]=(float)dummy;
}
// load material
m_all_icons [collectType] = material_manager->getMaterial(sIconFile);
m_all_icons[collectType] = material_manager->getMaterial(sIconFile);
m_all_icons[collectType]->getState()->ref();
//FIXME: something probably forgets to disable GL_CULL_FACE after enabling it,
@ -142,6 +135,21 @@ void CollectableManager::LoadNode(const lisp::Lisp* lisp, int collectType )
else
{
m_all_models[collectType] = 0;
#ifdef BULLET
m_all_extends[collectType] = btVector3(0.0f,0.0f,0.0f);
#endif
}
// Load special attributes for certain collectables
switch (collectType) {
case COLLECT_SPARK:
Spark::init (lisp, m_all_models[collectType]); break;
case COLLECT_MISSILE:
Missile::init(lisp, m_all_models[collectType]); break;
case COLLECT_HOMING:
Homing::init (lisp, m_all_models[collectType]); break;
default:;
} // switch
} // LoadNode

View File

@ -22,14 +22,18 @@
#include "lisp/parser.hpp"
#include "lisp/lisp.hpp"
#ifdef BULLET
#include "btBulletDynamicsCommon.h"
#endif
class Material;
class ssgEntity;
// The anvil and parachute must be at the end of the enum, and the
// zipper just before them (see collectable::hitRedHerring).
enum collectableType {COLLECT_NOTHING,
COLLECT_MISSILE, COLLECT_HOMING_MISSILE,
enum CollectableType {COLLECT_NOTHING,
COLLECT_MISSILE, COLLECT_HOMING,
COLLECT_SPARK, COLLECT_ZIPPER,
COLLECT_PARACHUTE, COLLECT_ANVIL,
#ifdef USE_MAGNETS
@ -41,17 +45,26 @@ class CollectableManager
{
protected:
Material* m_all_icons [COLLECT_MAX];
float m_all_speeds[COLLECT_MAX];
float m_all_max_distance[COLLECT_MAX]; // if a target is closer than this
float m_all_force_to_target[COLLECT_MAX]; // apply this force to move towards
// the target
float m_all_max_turn_angle[COLLECT_MAX]; // maximum turn angle for homing
ssgEntity* m_all_models[COLLECT_MAX];
btVector3 m_all_extends[COLLECT_MAX];
void LoadNode (const lisp::Lisp* lisp, int collectType);
public:
CollectableManager ();
void loadCollectables();
void removeTextures ();
void Load (int collectType, const char* filename);
Material* getIcon (int type) {return m_all_icons [type];}
float getSpeed (int type) {return m_all_speeds[type];}
ssgEntity* getModel (int type) {return m_all_models[type];}
Material* getIcon (int type) const {return m_all_icons [type]; }
ssgEntity* getModel (int type) const {return m_all_models[type]; }
float getForceToTarget(int type) const {return m_all_force_to_target[type]; }
float getMaxDistance (int type) const {return m_all_max_distance[type];}
float getMaxTurnAngle (int type) const {return m_all_max_turn_angle[type];}
#ifdef BULLET
const btVector3& getExtend (int type) const {return m_all_extends[type]; }
#endif
};
extern CollectableManager* collectable_manager;

View File

@ -74,5 +74,6 @@
#define NINETY_DEGREE_RAD (M_PI/2.0f)
#define DEGREE_TO_RAD(x) ((x)*M_PI/180.0f)
#define RAD_TO_DEGREE(x) ((x)*180.0f/M_PI)
#endif

View File

@ -26,12 +26,9 @@
Explosion::Explosion(sgCoord* coord) : ssgTransform()
{
this->ref();
ssgCutout *cut = new ssgCutout();
addKid(cut);
// Make sure that the transform object does not get deleted when it is
// removed from the scene graphs. This can happen when the explosion is
// moved to the deletedExplosion list in the projecile_manager.
ref();
addKid(cut); // derefing the explosion will free the cutout
m_seq = projectile_manager->getExplosionModel();
cut->addKid(m_seq);
init(coord);
@ -45,6 +42,7 @@ void Explosion::init(sgCoord* coord)
setTransform(coord);
m_step = -1;
scene->add(this);
printf("explosion\n");
}
//-----------------------------------------------------------------------------
@ -53,8 +51,8 @@ void Explosion::update (float dt)
if ( ++m_step >= m_seq->getNumKids() )
{
projectile_manager->FinishedExplosion();
scene->remove((ssgTransform*)this);
projectile_manager->FinishedExplosion();
return ;
}

View File

@ -30,9 +30,9 @@ public:
public:
Explosion(sgCoord* coord);
int inUse () {return (m_step >= 0); }
void init (sgCoord *coord);
void update (float delta_t);
int inUse () {return (m_step >= 0); }
bool hasEnded () {return m_step >= m_seq->getNumKids(); }
} ;

View File

@ -286,7 +286,7 @@ void HelpMenu::switch_to_second_screen()
widget_manager->add_wgt(WTOK_ITEMIMG2, 10, 13);
widget_manager->set_wgt_texture(WTOK_ITEMIMG2,
collectable_manager->getIcon(COLLECT_HOMING_MISSILE)->getState()->getTextureHandle());
collectable_manager->getIcon(COLLECT_HOMING)->getState()->getTextureHandle());
widget_manager->set_wgt_color(WTOK_ITEMIMG2, WGT_WHITE);
widget_manager->show_wgt_texture( WTOK_ITEMIMG2 );
widget_manager->set_wgt_round_corners(WTOK_ITEMIMG2, WGT_AREA_NONE);

View File

@ -100,11 +100,25 @@ RaceGUI::handle(GameAction ga, int value)
switch (ga)
{
case GA_DEBUG_ADD_SPARK:
if (world->m_race_setup.getNumPlayers() ==1 )
{
Kart* kart = world->getPlayerKart(0);
kart->setCollectable(COLLECT_SPARK, 10000);
}
break;
case GA_DEBUG_ADD_MISSILE:
if (world->m_race_setup.getNumPlayers() ==1 )
{
Kart* kart = world->getPlayerKart(0);
kart->setCollectable((rand()%2)?COLLECT_MISSILE :COLLECT_HOMING_MISSILE, 10000);
kart->setCollectable(COLLECT_MISSILE, 10000);
}
break;
case GA_DEBUG_ADD_HOMING:
if (world->m_race_setup.getNumPlayers() ==1 )
{
Kart* kart = world->getPlayerKart(0);
kart->setCollectable(COLLECT_HOMING, 10000);
}
break;
case GA_DEBUG_TOGGLE_FPS:
@ -708,7 +722,7 @@ void RaceGUI::drawSpeed(Kart* kart, int offset_x, int offset_y,
else
{
glTexCoord2f(0, 1);glVertex2i(offset_x, offset_y+width);
glTexCoord2f((speedRatio-0.5)*2, 1);glVertex2i((int)(offset_x+height*(speedRatio-0.5)*2), offset_y+height);
glTexCoord2f((speedRatio-0.5f)*2, 1);glVertex2i((int)(offset_x+height*(speedRatio-0.5f)*2), offset_y+height);
}
glEnd () ;

View File

@ -105,7 +105,7 @@
/>
<Tool
Name="VCCLCompilerTool"
WholeProgramOptimization="true"
WholeProgramOptimization="false"
AdditionalIncludeDirectories="..\..\bullet\src;&quot;$(GLUT_PATH)\include&quot;"
PreprocessorDefinitions="WIN32;NDEBUG"
MinimalRebuild="true"

View File

@ -704,6 +704,10 @@
RelativePath="../../../src\explosion.cpp"
>
</File>
<File
RelativePath="..\..\flyable.cpp"
>
</File>
<File
RelativePath="../../../src\game_manager.cpp"
>
@ -728,6 +732,10 @@
RelativePath="../../../src\history.cpp"
>
</File>
<File
RelativePath="..\..\homing.cpp"
>
</File>
<File
RelativePath="../../../src\isect.cpp"
>
@ -760,6 +768,10 @@
RelativePath="../../../src\material_manager.cpp"
>
</File>
<File
RelativePath="..\..\missile.cpp"
>
</File>
<File
RelativePath="../../../src\moveable.cpp"
>
@ -792,10 +804,6 @@
RelativePath="../../../src\player_kart.cpp"
>
</File>
<File
RelativePath="../../../src\projectile.cpp"
>
</File>
<File
RelativePath="../../../src\projectile_manager.cpp"
>
@ -848,6 +856,10 @@
RelativePath="../../../src\sound_plib.cpp"
>
</File>
<File
RelativePath="..\..\spark.cpp"
>
</File>
<File
RelativePath="../../../src\ssg_help.cpp"
>
@ -880,10 +892,6 @@
RelativePath="../../../src\user_config.cpp"
>
</File>
<File
RelativePath="../../../src\utils.cpp"
>
</File>
<File
RelativePath="..\..\widget.cpp"
>
@ -1070,6 +1078,10 @@
RelativePath="../../../src\explosion.hpp"
>
</File>
<File
RelativePath="..\..\flyable.hpp"
>
</File>
<File
RelativePath="../../../src\game_manager.hpp"
>
@ -1094,6 +1106,14 @@
RelativePath="../../../src\history.hpp"
>
</File>
<File
RelativePath="..\..\homing.hpp"
>
</File>
<File
RelativePath="..\..\input.hpp"
>
</File>
<File
RelativePath="../../../src\isect.hpp"
>
@ -1122,6 +1142,10 @@
RelativePath="../../../src\material_manager.hpp"
>
</File>
<File
RelativePath="..\..\missile.hpp"
>
</File>
<File
RelativePath="../../../src\moveable.hpp"
>
@ -1166,10 +1190,6 @@
RelativePath="../../../src\player_kart.hpp"
>
</File>
<File
RelativePath="../../../src\projectile.hpp"
>
</File>
<File
RelativePath="../../../src\projectile_manager.hpp"
>
@ -1234,6 +1254,10 @@
RelativePath="../../../src\sound_plib.hpp"
>
</File>
<File
RelativePath="..\..\spark.hpp"
>
</File>
<File
RelativePath="../../../src\ssg_help.hpp"
>
@ -1266,10 +1290,6 @@
RelativePath="../../../src\user_config.hpp"
>
</File>
<File
RelativePath="../../../src\utils.hpp"
>
</File>
<File
RelativePath="..\..\widget.hpp"
>

View File

@ -155,6 +155,8 @@ enum GameAction
GA_LEAVE_RACE, // Switch from race to menu.
GA_DEBUG_ADD_MISSILE,
GA_DEBUG_ADD_SPARK,
GA_DEBUG_ADD_HOMING,
GA_DEBUG_TOGGLE_FPS,
GA_DEBUG_BULLET,
GA_DEBUG_TOGGLE_WIREFRAME,

View File

@ -349,6 +349,7 @@ void Kart::reset()
m_race_lap = -1;
m_lap_start_time = -1.0f;
m_time_at_last_lap = 99999.9f;
m_shortcut_count = 0;
m_shortcut_sector = Track::UNKNOWN_SECTOR;
m_shortcut_type = SC_NONE;
@ -927,8 +928,6 @@ float Kart::handleWheelie(float dt)
// -----------------------------------------------------------------------------
void Kart::updatePhysics (float dt)
{
#ifdef BULLET
float engine_power = getActualWheelForce() + handleWheelie(dt);
if(m_attachment.getType()==ATTACH_PARACHUTE) engine_power*=0.2f;
@ -1011,222 +1010,6 @@ void Kart::updatePhysics (float dt)
//at low velocity, forces on kart push it back and forth so we ignore this
if(fabsf(m_speed) < 0.2f) // quick'n'dirty workaround for bug 1776883
m_speed = 0;
#else // ! BULLET
m_skid_front = m_skid_rear = false;
sgVec3 AirResistance, SysResistance;
// Get some values once, to avoid calling them more than once.
const float WORLD_GRAVITY = world->getGravity();
const float WHEEL_BASE = getWheelBase();
const float MASS = getMass(); // includes m_attachment.WeightAdjust
const float AIR_FRICTION = getAirResistance(); // includes attachmetn.AirFrictAdjust
const float ROLL_RESIST = getRollResistance();
if(m_wheelie_angle>0.0f)
{
m_velocity.xyz[1]-=getWheelieSpeedBoost()*m_wheelie_angle/getWheelieMaxPitch();
if(m_velocity.xyz[1]<0) m_velocity.xyz[1]=0.0;
}
// Handle throttle and brakes
// ==========================
float throttle;
if(m_on_ground)
{
if(m_controls.brake)
{
throttle = m_velocity.xyz[1]<0.0f ? -1.0f : -getBrakeFactor();
}
else
{ // not braking
throttle = m_velocity.xyz[1]<0.0f ? getBrakeFactor()
: m_controls.accel*m_current_friction*m_current_friction;
}
// Handle wheelies
// ===============
if ( m_controls.wheelie && m_velocity.xyz[1] >=
getMaxSpeed()*getWheelieMaxSpeedRatio())
{
m_velocity.hpr[0]=0.0;
if ( m_wheelie_angle < getWheelieMaxPitch() )
m_wheelie_angle += getWheeliePitchRate() * dt;
else
m_wheelie_angle = getWheelieMaxPitch();
}
else if ( m_wheelie_angle > 0.0f )
{
m_wheelie_angle -= getWheelieRestoreRate() * dt;
if ( m_wheelie_angle <= 0.0f ) m_wheelie_angle = 0.0f ;
}
}
else
{ // not on ground
throttle = 0.0;
} // if !m_on_ground
float ForceLong = throttle * getMaxPower();
// apply air friction and system friction
AirResistance[0] = 0.0f;
AirResistance[1] = AIR_FRICTION*m_velocity.xyz[1]*fabs(m_velocity.xyz[1]);
AirResistance[2] = 0.0f;
SysResistance[0] = ROLL_RESIST*m_velocity.xyz[0];;
SysResistance[1] = ROLL_RESIST*m_velocity.xyz[1];
SysResistance[2] = 0.0f;
//
// Compute longitudinal acceleration for slipping
// ----------------------------------------------
const float FORCE_ON_REAR_TIRE = 0.5f*MASS*WORLD_GRAVITY + m_prev_accel*MASS*getHeightCOG()/WHEEL_BASE;
const float FORCE_ON_FRONT_TIRE = MASS*WORLD_GRAVITY - FORCE_ON_REAR_TIRE;
float maxGrip = std::max(FORCE_ON_REAR_TIRE,FORCE_ON_FRONT_TIRE)*getTireGrip();
// If the kart is on ground, modify the grip by the friction
// modifier for the texture/terrain.
if(m_on_ground && m_material_hot) maxGrip *= m_material_hot->getFriction();
// Gravity handling
// ================
float ForceGravity;
if(m_on_ground)
{
if(m_normal_hot)
{
// Adjust pitch and roll according to the current terrain. To compute
// the correspondant angles, we consider first a normalised line
// pointing into the direction the kart is facing (pointing from (0,0,0)
// to (x,y,0)). The angle between this line and the triangle the kart is
// on determines the pitch. Similartly the roll is computed, using a
// normalised line pointing to the right of the kart, for which we simply
// use (-y,x,0).
const float kartAngle = m_curr_pos.hpr[0]*M_PI/180.0f;
const float X = -sin(kartAngle);
const float Y = cos(kartAngle);
// Compute the angle between the normal of the plane and the line to
// (x,y,0). (x,y,0) is normalised, so are the coordinates of the plane,
// simplifying the computation of the scalar product.
float pitch = ( (*m_normal_hot)[0]*X + (*m_normal_hot)[1]*Y ); // use ( x,y,0)
float roll = (-(*m_normal_hot)[0]*Y + (*m_normal_hot)[1]*X ); // use (-y,x,0)
// The actual angle computed above is between the normal and the (x,y,0)
// line, so to compute the actual angles 90 degrees must be subtracted.
pitch = acosf(pitch)/M_PI*180.0f-90.0f;
roll = acosf(roll )/M_PI*180.0f-90.0f;
// if dt is too big, the relaxation will overshoot, and the
// karts will either be hopping, or even turn upside down etc.
if(dt<=0.05)
{
# define RELAX(oldVal, newVal) (oldVal + (newVal-oldVal)*dt*20.0f)
m_curr_pos.hpr[1] = RELAX(m_curr_pos.hpr[1],pitch);
m_curr_pos.hpr[2] = RELAX(m_curr_pos.hpr[2],roll );
}
else
{
m_curr_pos.hpr[1] = pitch;
m_curr_pos.hpr[2] = roll ;
}
if(fabsf(m_curr_pos.hpr[1])>fabsf(pitch)) m_curr_pos.hpr[1]=pitch;
if(fabsf(m_curr_pos.hpr[2])>fabsf(roll )) m_curr_pos.hpr[2]=roll;
}
if(m_controls.jump)
{ // ignore gravity down when jumping
ForceGravity = stk_config->m_jump_impulse*WORLD_GRAVITY;
}
else
{ // kart is on groud and not jumping
if(user_config->m_improved_physics)
{
// FIXME:
// While these physics computation is correct, it is very difficult
// to drive, esp. the sandtrack: the grades (with the current
// physics parameters) are too steep, so the kart needs a very high
// initial velocity to be able to reach the top. Especially the
// AI gets stuck very easily! Perhaps reduce the forces somewhat?
const float PITCH_IN_RAD = m_curr_pos.hpr[1]*M_PI/180.0f;
ForceGravity = -WORLD_GRAVITY * MASS * cos(PITCH_IN_RAD);
ForceLong -= WORLD_GRAVITY * MASS * sin(PITCH_IN_RAD);
}
else
{
ForceGravity = -WORLD_GRAVITY * MASS;
}
}
}
else
{ // kart is not on ground, gravity applies all to z axis.
ForceGravity = -WORLD_GRAVITY * MASS;
}
m_velocity.xyz[2] += ForceGravity / MASS * dt;
if(m_wheelie_angle <= 0.0f && m_on_ground)
{
// At low speed, the advanced turning mode can result in 'flickering', i.e.
// very quick left/right movements. The reason might be:
// 1) integration timestep to big
// 2) the kart turning too much, thus 'oversteering', which then gets
// corrected (which might be caused by wrongly tuned physics parameters,
// or the too big timestep mentioned above
// Since at lower speed the simple turning algorithm is good enough,
// the advanced sliding turn algorithm is only used at higher speeds.
// FIXME: for now, only use the simple steering algorithm.
// so the test for 'lower speed' is basically disabled for now,
// since the velocity will always be lower than 1.5*100000.0f
if(fabsf(m_velocity.xyz[1])<150000.0f)
{
const float MSA = getMaxSteerAngle();
m_velocity.hpr[0] = m_controls.lr * ((m_velocity.xyz[1]>=0.0f) ? MSA : -MSA);
if(m_velocity.hpr[0]> MSA) m_velocity.hpr[0] = MSA; // In case the AI sets
if(m_velocity.hpr[0]<-MSA) m_velocity.hpr[0] = -MSA; // m_controls.lr >1 or <-1
}
else
{
const float STEER_ANGLE = m_controls.lr*getMaxSteerAngle()*M_PI/180.0f;
const float TURN_DISTANCE = m_velocity.hpr[0]*M_PI/180.0f * WHEEL_BASE/2.0f;
const float SLIP_ANGLE_FRONT = atan((m_velocity.xyz[0]+TURN_DISTANCE)
/fabsf(m_velocity.xyz[1]))
- sgn(m_velocity.xyz[1])*STEER_ANGLE;
const float SLIP_ANGLE_REAR = atan((m_velocity.xyz[0]-TURN_DISTANCE)
/fabsf(m_velocity.xyz[1]));
const float FORCE_LAT_FRONT = NormalizedLateralForce(SLIP_ANGLE_FRONT, getCornerStiffF())
* FORCE_ON_FRONT_TIRE - SysResistance[0]*0.5f;
const float FORCE_LAT_REAR = NormalizedLateralForce(SLIP_ANGLE_REAR, getCornerStiffR())
* FORCE_ON_REAR_TIRE - SysResistance[0]*0.5f;
const float CORNER_FORCE = FORCE_LAT_REAR + cos(STEER_ANGLE)*FORCE_LAT_FRONT;
m_velocity.xyz[0] = CORNER_FORCE/MASS*dt;
const float TORQUE = FORCE_LAT_REAR *WHEEL_BASE/2
- cos(STEER_ANGLE)*FORCE_LAT_FRONT*WHEEL_BASE/2;
const float ANGLE_ACCELERATION = TORQUE/getInertia();
m_velocity.hpr[0] += ANGLE_ACCELERATION*dt*180.0f/M_PI;
} // fabsf(m_velocity.xyz[1])<0.5
} // m_wheelie_angle <=0.0f && m_on_ground
// Longitudinal accelleration
// ==========================
const float EFECTIVE_FORCE = (ForceLong-AirResistance[1]-SysResistance[1]);
// Slipping: more force than what can be supported by the back wheels
// --> reduce the effective force acting on the kart - currently
// by an arbitrary value.
if(fabs(EFECTIVE_FORCE)>maxGrip)
{
// EFECTIVE_FORCE *= 0.4f;
// m_skid_rear = true;
} // while EFECTIVE_FORCE>maxGrip
float ACCELERATION = EFECTIVE_FORCE / MASS;
m_velocity.xyz[1] += ACCELERATION * dt;
m_prev_accel = ACCELERATION;
if(m_wheelie_angle>0.0f)
{
m_velocity.xyz[1]+=
getWheelieSpeedBoost()*m_wheelie_angle/getWheelieMaxPitch();
if(m_velocity.xyz[1]<0) m_velocity.xyz[1]=0.0;
}
#endif
} // updatePhysics
//-----------------------------------------------------------------------------
@ -1478,7 +1261,7 @@ void Kart::loadData()
lod -> addKid ( obj ) ;
lod -> setRanges ( r, 2 ) ;
this-> getModel() -> addKid ( lod ) ;
this-> getModelTransform() -> addKid ( lod ) ;
// Attach Particle System
//JH sgCoord pipe_pos = {{0, 0, .3}, {0, 0, 0}} ;
@ -1495,7 +1278,7 @@ void Kart::loadData()
m_shadow = createShadow(m_kart_properties->getShadowFile(), -1, 1, -1, 1);
m_shadow->ref();
m_model->addKid ( m_shadow );
m_model_transform->addKid ( m_shadow );
} // loadData
//-----------------------------------------------------------------------------
@ -1548,7 +1331,7 @@ void Kart::placeModel ()
// c.xyz[2] += 0.3f*fabs(sin(m_wheelie_angle*SG_DEGREES_TO_RADIANS));
const float CENTER_SHIFT = getGravityCenterShift();
c.xyz[2] -= (0.5f-CENTER_SHIFT)*m_kart_height; // adjust for center of gravity
m_model->setTransform(&c);
m_model_transform->setTransform(&c);
// Check if a kart needs to be rescued.
if((fabs(m_curr_pos.hpr[2])>60 &&

View File

@ -163,7 +163,7 @@ public:
m_wheelie_angle=angle;
m_zipper_time_left=time;
}
void setCollectable (collectableType t, int n)
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; }

View File

@ -42,7 +42,7 @@ public:
const int getKartId (const std::string IDENT);
void loadKartData (bool dont_load_models=false);
const float getMaximumSteeringAngle() {return m_max_steer_angle;}
const unsigned int getNumberOfKarts () {return m_karts_properties.size();}
const unsigned int getNumberOfKarts () {return (unsigned int)m_karts_properties.size();}
/** Return len random karts */
std::vector<std::string> getRandomKarts (int len);

View File

@ -32,10 +32,8 @@
#include "plib/ul.h"
#include "loader.hpp"
#include "world.hpp"
#ifdef BULLET
#include "btBulletDynamicsCommon.h"
#include "moving_physics.hpp"
#endif
#include "moving_texture.hpp"
#include "translation.hpp"
#include "material_manager.hpp"
@ -361,20 +359,16 @@ ssgBranch *Loader::createBranch(char *data) const
{
ssgTexTrans *br = new ssgTexTrans();
Callback *c = new MovingTexture(data, br);
br->setUserData(new ssgBase());
br->setName("MovingTexture");
callback_manager->addCallback(c, m_current_callback_type);
return br;
}
if(strncmp("physics", data, strlen("physics")) == 0)
{
#ifdef BULLET
MovingPhysics *mp = new MovingPhysics(std::string(data));
ssgTransform *tr = new ssgTransform();
MovingPhysics *mp = new MovingPhysics(std::string(data), tr);
callback_manager->addCallback(mp, m_current_callback_type);
return mp;
#else
return NULL;
#endif
return tr;
}
fprintf(stderr, "Warning: Ignoring userdata '%s'\n", data);
return NULL ;

View File

@ -27,15 +27,13 @@
Moveable::Moveable (bool bHasHistory)
{
#ifdef BULLET
m_body = 0;
m_motion_state = 0;
#endif
m_shadow = 0;
m_first_time = true ;
m_model = new ssgTransform();
m_model_transform = new ssgTransform();
m_model->ref();
m_model_transform->ref();
sgZeroVec3 ( m_reset_pos.xyz ) ; sgZeroVec3 ( m_reset_pos.hpr ) ;
@ -55,11 +53,9 @@ Moveable::Moveable (bool bHasHistory)
//-----------------------------------------------------------------------------
Moveable::~Moveable()
{
#ifdef BULLET
// The body is being removed from the world in kart/projectile
if(m_body) delete m_body;
if(m_motion_state) delete m_motion_state;
#endif
if(m_history_velocity)
{
delete [] m_history_velocity;
@ -71,9 +67,6 @@ Moveable::~Moveable()
//-----------------------------------------------------------------------------
void Moveable::reset ()
{
#ifndef BULLET
m_on_ground = true;
#endif
m_collided = false;
m_crashed = false;
m_material_hot = NULL;
@ -87,7 +80,6 @@ void Moveable::reset ()
} // reset
//-----------------------------------------------------------------------------
#ifdef BULLET
void Moveable::createBody(float mass, btTransform& trans,
btCollisionShape *shape, MoveableType m) {
@ -102,7 +94,7 @@ void Moveable::createBody(float mass, btTransform& trans,
m_body->setUserPointer(this);
setMoveableType(m);
} // createBody
#endif
//-----------------------------------------------------------------------------
void Moveable::update (float dt)
{
@ -140,7 +132,6 @@ void Moveable::update (float dt)
sgVec3 start ; sgCopyVec3 (start, m_curr_pos.xyz );
sgVec3 end ; sgCopyVec3 (end , result[3] );
const float HOT = collectIsectData(start, end );
sgCopyVec3 (result[3], end) ;
@ -177,12 +168,6 @@ void Moveable::update (float dt)
sgCopyCoord(&(m_history_position[history->GetCurrentIndex()]), &m_curr_pos);
}
} // if m_history_position
const float HAT = m_curr_pos.xyz[2]-HOT;
#ifndef BULLET
m_on_ground = ( HAT <= 0.01 );
doCollisionAnalysis(dt, HOT);
#endif
placeModel () ;
@ -250,10 +235,6 @@ void Moveable::ReadHistory(char* s, int kartNumber, int indx)
} // ReadHistory
//-----------------------------------------------------------------------------
#ifndef BULLET
void Moveable::doCollisionAnalysis ( float,float ) { /* Empty by Default. */ }
#endif
#define ISECT_STEP_SIZE 0.4f
#define COLLISION_SPHERE_RADIUS 0.6f
@ -371,8 +352,7 @@ float Moveable::getIsectData ( sgVec3 start, sgVec3 end )
m_material_hot = material_manager->getMaterial(m_leaf);
// Only rescue the kart if it (nearly) touches the reset-material,
// not only when it is above it. The condition for touching
// a material is coarser then for the m_on_ground condition
// (which tests for <0.01) - since the kart might have been falling
// a material is somewha coars, since the kart might have been falling
// for quite some time, it might be really fast, so I guess a somewhat
// coarser test is better for that case.
if(m_material_hot->isReset() &&

View File

@ -41,7 +41,7 @@
class Moveable
{
public:
enum MoveableType {MOV_KART, MOV_PROJECTILE} ;
enum MoveableType {MOV_KART, MOV_PROJECTILE, MOV_TRACK} ;
protected:
MoveableType m_moveable_type; /* used when upcasting bullet user pointers */
sgCoord m_reset_pos; /* Where to start in case of a reset */
@ -50,15 +50,12 @@ protected:
sgVec3 m_abs_velocity; /* world coordinates' velocity vector */
sgVec4* m_normal_hot; /* plane on which HOT was computed */
Material* m_material_hot; /* Material at HOT */
ssgTransform* m_model;
ssgTransform* m_model_transform; // The transform where the model is under
ssgTransform* m_shadow;
int m_collided;
int m_crashed;
sgVec3 m_surface_avoidance_vector ;
int m_first_time ;
#ifndef BULLET
int m_on_ground ;
#endif
float collectIsectData ( sgVec3 start, sgVec3 end ) ;
sgCoord* m_history_velocity;
@ -76,10 +73,7 @@ public:
Moveable (bool bHasHistory=false);
virtual ~Moveable();
ssgTransform* getModel () {return m_model ; }
#ifndef BULLET
int isOnGround () {return m_on_ground; }
#endif
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; }
@ -87,7 +81,7 @@ public:
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 () {m_model->setTransform(&m_curr_pos); }
virtual void placeModel () {m_model_transform->setTransform(&m_curr_pos); }
virtual void handleZipper () {};
virtual void reset ();
virtual void update (float dt) ;
@ -104,14 +98,12 @@ public:
float getIsectData (sgVec3 start, sgVec3 end );
void WriteHistory (char* s, int kartNumber, int indx);
void ReadHistory (char* s, int kartNumber, int indx);
#ifdef BULLET
btRigidBody* getBody () const {return m_body; }
void createBody(float mass, btTransform& trans,
btCollisionShape *shape, MoveableType m);
void getTrans (btTransform* t) const
{m_motion_state->getWorldTransform(*t);}
void setTrans (btTransform& t){m_motion_state->setWorldTransform(t);}
#endif
}
; // class Moveable

View File

@ -26,17 +26,16 @@
#include "ssg_help.hpp"
#include "scene.hpp"
#ifdef BULLET
// -----------------------------------------------------------------------------
MovingPhysics::MovingPhysics(const std::string data)
: ssgTransform(), Callback()
MovingPhysics::MovingPhysics(const std::string data, ssgTransform* trans)
: Callback()
{
m_trans = trans;
m_shape = NULL;
m_body = NULL;
m_motion_state = NULL;
m_mass = 1;
setUserData(new ssgBase());
ref();
m_trans->setUserData(new ssgBase()); // prevent tree optimisations to remove this node
std::vector<std::string> parameters = StringUtils::split(data, ' ');
if(parameters.size()<2)
@ -81,8 +80,8 @@ MovingPhysics::MovingPhysics(const std::string data)
// -----------------------------------------------------------------------------
MovingPhysics::~MovingPhysics()
{
world->getPhysics()->getPhysicsWorld()->removeRigidBody(m_body);
deRef();
scene->remove(m_trans);
world->getPhysics()->removeBody(m_body);
delete m_shape;
delete m_motion_state;
delete m_body;
@ -104,15 +103,15 @@ void MovingPhysics::init()
// 1. Remove the object from the graph and attach it to the root
// -------------------------------------------------------------
if(getNumParents()>1)
if(m_trans->getNumParents()>1)
{
fprintf(stderr, "WARNING: physical object with more than one parent!!\n");
return;
}
ssgBranch *parent = getParent(0);
ssgBranch *parent = m_trans->getParent(0);
parent->removeKid(this);
scene->add(this);
scene->add(m_trans);
parent->removeKid(m_trans);
// 2. Determine the original position of the object
// ------------------------------------------------
@ -161,18 +160,18 @@ void MovingPhysics::init()
// 3. Determine size of the object
// -------------------------------
float x_min, x_max, y_min, y_max, z_min, z_max, radius;
MinMax(this, &x_min, &x_max, &y_min, &y_max, &z_min, &z_max);
MinMax(m_trans, &x_min, &x_max, &y_min, &y_max, &z_min, &z_max);
m_half_height = 0.5f*(z_max-z_min);
switch (m_body_type)
{
case BODY_CONE: radius = 0.5f*std::max(x_max-x_min, y_max-y_min);
m_shape = new btConeShape(radius, z_max-z_min);
setName("cone");
m_trans->setName("cone");
break;
case BODY_BOX: m_shape = new btBoxShape(btVector3(0.5f*(x_max-x_min),
0.5f*(y_max-y_min),
0.5f*(z_max-z_min) ) );
setName("box");
m_trans->setName("box");
break;
case BODY_NONE: fprintf(stderr, "WARNING: Uninitialised moving shape\n");
break;
@ -204,10 +203,9 @@ void MovingPhysics::update(float dt)
// Transfer the new position and hpr to m_curr_pos
sgCoord m_curr_pos;
sgSetCoord(&m_curr_pos, m);
setTransform(&m_curr_pos);
m_trans->setTransform(&m_curr_pos);
} // update
// -----------------------------------------------------------------------------
#endif
/* EOF */

View File

@ -24,20 +24,21 @@
#include "btBulletDynamicsCommon.h"
#include "callback.hpp"
class MovingPhysics : public ssgTransform, public Callback
class MovingPhysics : public Callback
{
public:
enum bodyTypes {BODY_NONE, BODY_CONE, BODY_BOX};
protected:
bodyTypes m_body_type;
ssgTransform *m_trans;
btCollisionShape *m_shape;
btRigidBody *m_body;
btDefaultMotionState *m_motion_state;
float m_half_height;
float m_mass;
public:
MovingPhysics (const std::string data);
MovingPhysics (const std::string data, ssgTransform *trans);
~MovingPhysics ();
void update (float dt);
void init ();

View File

@ -26,6 +26,9 @@
MovingTexture::MovingTexture(char *data, ssgBranch *branch)
{
m_branch = branch;
branch->setUserData(new ssgBase());
branch->setName("MovingTexture");
m_branch->ref();
m_phase = 0.0f;
m_mode = MODE_FORWARD;

View File

@ -25,7 +25,7 @@
#include "physics.hpp"
#include "ssg_help.hpp"
#include "world.hpp"
#include "projectile.hpp"
#include "flyable.hpp"
#include "moving_physics.hpp"
#include "user_config.hpp"
@ -34,22 +34,19 @@
/** Initialise physics. */
float Physics::NOHIT=-99999.9f;
float const Physics::NOHIT=-99999.9f;
Physics::Physics(float gravity)
Physics::Physics(float gravity) : btSequentialImpulseConstraintSolver()
{
m_collision_conf = new btDefaultCollisionConfiguration();
m_dispatcher = new btCollisionDispatcher(m_collision_conf);
btVector3 worldMin(-1000, -1000, -1000);
btVector3 worldMax( 1000, 1000, 1000);
m_axis_sweep = new btAxisSweep3(worldMin, worldMax);
m_constraint_solver = new btSequentialImpulseConstraintSolver();
m_dynamics_world = new btDiscreteDynamicsWorld(m_dispatcher,
m_axis_sweep,
m_constraint_solver,
this,
m_collision_conf);
m_dynamics_world->setGravity(btVector3(0.0f, 0.0f, -gravity));
if(user_config->m_bullet_debug)
@ -63,12 +60,11 @@ Physics::Physics(float gravity)
//-----------------------------------------------------------------------------
Physics::~Physics()
{
delete m_dispatcher;
if(user_config->m_bullet_debug) delete m_debug_drawer;
delete m_dynamics_world;
delete m_axis_sweep;
delete m_dispatcher;
delete m_collision_conf;
delete m_constraint_solver;
if(user_config->m_bullet_debug) delete m_debug_drawer;
} // ~Physics
@ -178,21 +174,112 @@ void Physics::removeKart(const Kart *kart)
//-----------------------------------------------------------------------------
void Physics::update(float dt)
{
// Bullet can report the same collision more than once (up to 4
// contact points per collision. Additionally, more than one internal
// substep might be taken, resulting in potentially even more
// duplicates. To handle this, all collisions (i.e. pair of objects)
// are stored in a vector, but only one entry per collision pair
// of objects.
m_all_collisions.clear();
m_dynamics_world->stepSimulation(dt);
// ??? m_dynamicsWorld->updateAabbs();
handleCollisions();
// Now handle the actual collision. Note: rockets can not be removed
// inside of this loop, since the same rocket might hit more than one
// other object. So, only a flag is set in the rockets, the actual
// clean up is then done later in the projectile manager.
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
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
{
((Flyable*)(p->a))->hitTrack();
}
else if(p->type_b==Moveable::MOV_KART) // projectile hit kart
{
Flyable *f=(Flyable*)(p->a);
f->explode((Kart*)(p->b));
}
else // projectile hits projectile
{
((Flyable*)(p->a))->explode(NULL);
((Flyable*)(p->b))->explode(NULL);
}
}
} // for all p in m_all_collisions
} // update
//-----------------------------------------------------------------------------
void Physics::handleCollisions() {
int numManifolds = m_dispatcher->getNumManifolds();
for(int i=0; i<numManifolds; i++)
/** Handles the special case of two karts colliding with each other
* If both karts have a bomb, they'll explode immediately
*/
void Physics::KartKartCollision(Kart *kartA, Kart *kartB)
{
Attachment *attachmentA=kartA->getAttachment();
Attachment *attachmentB=kartB->getAttachment();
if(attachmentA->getType()==ATTACH_BOMB)
{
// If both karts have a bomb, explode them immediately:
if(attachmentB->getType()==ATTACH_BOMB)
{
attachmentA->setTimeLeft(0.0f);
attachmentB->setTimeLeft(0.0f);
}
else // only A has a bomb, move it to B (unless it was from B)
{
if(attachmentA->getPreviousOwner()!=kartB)
{
attachmentA->moveBombFromTo(kartA, kartB);
}
}
}
else if(attachmentB->getType()==ATTACH_BOMB &&
attachmentB->getPreviousOwner()!=kartA)
{
attachmentB->moveBombFromTo(kartB, kartA);
}
if(kartA->isPlayerKart()) sound_manager->playSfx(SOUND_CRASH);
if(kartB->isPlayerKart()) sound_manager->playSfx(SOUND_CRASH);
} // KartKartCollision
//-----------------------------------------------------------------------------
/** This function is called at each internal bullet timestep. It is used
* here to do the collision handling: using the contact manifolds after a
* physics time step might miss some collisions (when more than one internal
* time step was done, and the collision is added and removed).
**/
btScalar Physics::solveGroup(btCollisionObject** bodies, int numBodies,
btPersistentManifold** manifold,int numManifolds,
btTypedConstraint** constraints,int numConstraints,
const btContactSolverInfo& info,
btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc,
btDispatcher* dispatcher) {
btScalar returnValue=
btSequentialImpulseConstraintSolver::solveGroup(bodies, numBodies, manifold,
numManifolds, constraints,
numConstraints, info,
debugDrawer, stackAlloc,
dispatcher);
int currentNumManifolds = m_dispatcher->getNumManifolds();
// We can't explode a rocket in a loop, since a rocket might collide with
// more than one object, and/or more than once with each object (if there
// is more than one collision point). So keep a list of rockets that will
// be exploded after the collisions
std::vector<Moveable*> rocketsToExplode;
for(int i=0; i<currentNumManifolds; i++)
{
btPersistentManifold* contactManifold = m_dynamics_world->getDispatcher()->getManifoldByIndexInternal(i);
btCollisionObject* objA = static_cast<btCollisionObject*>(contactManifold->getBody0());
btCollisionObject* objB = static_cast<btCollisionObject*>(contactManifold->getBody1());
contactManifold->refreshContactPoints(objA->getWorldTransform(),objB->getWorldTransform());
int numContacts = contactManifold->getNumContacts();
if(!numContacts) continue; // no real collision
@ -200,63 +287,35 @@ void Physics::handleCollisions() {
Moveable *movA = static_cast<Moveable*>(objA->getUserPointer());
Moveable *movB = static_cast<Moveable*>(objB->getUserPointer());
if(!numContacts) continue; // no real collision
// 1) object A is a track
// =======================
if(!movA)
{
if(!movB)
{ // 1.1) track hits track ??
// ------------------------
continue; // --> ignore
}
else if(movB->getMoveableType()==Moveable::MOV_PROJECTILE)
{ // 1.2 projectile hits track
if(movB && movB->getMoveableType()==Moveable::MOV_PROJECTILE)
{ // 1.1 projectile hits track
// -------------------------
Projectile *p=(Projectile*)movB;
p->explode(NULL); // explode on track
}
else
{ // 1.3 kart hits track
// -------------------
continue;
m_all_collisions.push_back(CollisionPair(movB, Moveable::MOV_PROJECTILE,
NULL, Moveable::MOV_TRACK ));
}
}
// 2) object a is a kart
// =====================
else if(movA->getMoveableType()==Moveable::MOV_KART)
{
if(!movB)
{ // 2.1) kart hits track
// --------------------
continue; // --> ignore
}
else if(movB->getMoveableType()==Moveable::MOV_PROJECTILE)
{ // 2.2 projectile hits kart
if(movB && movB->getMoveableType()==Moveable::MOV_PROJECTILE)
{ // 2.1 projectile hits kart
// -------------------------
Projectile *p=(Projectile*)movB;
p->explode((Kart*)movA);
m_all_collisions.push_back(CollisionPair(movB, Moveable::MOV_PROJECTILE,
movA, Moveable::MOV_KART ));
}
else if(movB->getMoveableType()==Moveable::MOV_KART)
{ // 2.3 kart hits kart
else if(movB && movB->getMoveableType()==Moveable::MOV_KART)
{ // 2.2 kart hits kart
// ------------------
Kart *kartA = (Kart*)movA;
Kart *kartB = (Kart*)movB;
m_all_collisions.push_back(CollisionPair(movA, Moveable::MOV_KART,
movB, Moveable::MOV_KART ));
// First check for bomb attachments
Attachment *attachmentA=kartA->getAttachment();
if(attachmentA->getType()==ATTACH_BOMB &&
attachmentA->getPreviousOwner()!=kartB)
{
attachmentA->moveBombFromTo(kartA, kartB);
}
Attachment *attachmentB=kartB->getAttachment();
if(attachmentB->getType()==ATTACH_BOMB &&
attachmentB->getPreviousOwner()!=kartA)
{
attachmentB->moveBombFromTo(kartB, kartA);
}
if(kartA->isPlayerKart()) sound_manager->playSfx(SOUND_CRASH);
if(kartB->isPlayerKart()) sound_manager->playSfx(SOUND_CRASH);
}
}
// 3) object is a projectile
@ -266,19 +325,20 @@ void Physics::handleCollisions() {
if(!movB)
{ // 3.1) projectile hits track
// --------------------------
((Projectile*)movA)->explode(NULL);
m_all_collisions.push_back(CollisionPair(movA, Moveable::MOV_PROJECTILE,
NULL, Moveable::MOV_TRACK ));
}
else if(movB->getMoveableType()==Moveable::MOV_PROJECTILE)
{ // 3.2 projectile hits projectile
// ------------------------------
((Projectile*)movA)->explode(NULL);
((Projectile*)movB)->explode(NULL);
m_all_collisions.push_back(CollisionPair(movA, Moveable::MOV_PROJECTILE,
movB, Moveable::MOV_PROJECTILE));
}
else if(movB->getMoveableType()==Moveable::MOV_KART)
{ // 3.3 projectile hits kart
// ------------------------
Projectile *p=(Projectile*)movA;
p->explode((Kart*)movB);
m_all_collisions.push_back(CollisionPair(movA, Moveable::MOV_PROJECTILE,
movB, Moveable::MOV_KART ));
}
}
// 4) Nothing else should happen
@ -288,7 +348,9 @@ void Physics::handleCollisions() {
assert("Unknown user pointer");
}
} // for i<numManifolds
} // handleCollisions
return returnValue;
} // solveGroup
// -----------------------------------------------------------------------------
float Physics::getHAT(btVector3 pos)
@ -300,8 +362,9 @@ float Physics::getHAT(btVector3 pos)
m_dynamics_world->rayTest(pos, to_pos, rayCallback);
if(!rayCallback.HasHit()) return NOHIT;
return rayCallback.m_hitPointWorld.getZ() - pos.getZ();
} // getHOT
return pos.getZ()-rayCallback.m_hitPointWorld.getZ();
} // getHAT
// -----------------------------------------------------------------------------
bool Physics::getTerrainNormal(btVector3 pos, btVector3* normal)
{

View File

@ -21,24 +21,71 @@
#define HEADER_PHYSICS_H
#include "kart.hpp"
#include "flyable.hpp"
#include <plib/sg.h>
#include <set>
#ifdef BULLET
#include "btBulletDynamicsCommon.h"
#include "bullet/Demos/OpenGL/GLDebugDrawer.h"
class Physics
class Physics : public btSequentialImpulseConstraintSolver
{
protected:
private:
btDynamicsWorld *m_dynamics_world;
Kart *m_kart;
GLDebugDrawer *m_debug_drawer;
btCollisionDispatcher *m_dispatcher;
btBroadphaseInterface *m_axis_sweep;
btDefaultCollisionConfiguration *m_collision_conf;
btConstraintSolver *m_constraint_solver;
void convertTrack(ssgEntity *track, sgMat4 m, btTriangleMesh* track_mesh);
// Bullet can report the same collision more than once (up to 4
// contact points per collision. Additionally, more than one internal
// substep might be taken, resulting in potentially even more
// duplicates. To handle this, all collisions (i.e. pair of objects)
// are stored in a vector, but only one entry per collision pair
// of objects.
// While this is a natural application of std::set, the set has some
// overhead (since it will likely use a tree to sort the entries).
// Considering that the number of collisions is usually rather small
// a simple list and linear search is being used here.
class CollisionPair {
public:
void *a, *b;
Moveable::MoveableType 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) {
a=b1;b=a1; type_a=btype; type_b=atype;
} else {
a=a1; b=b1; type_a=atype; type_b=btype;
}
}; // CollisionPair
bool operator==(const CollisionPair p) {
return (p.a==a && p.b==b);
}
};
// This class is the list of collision objects, where each collision
// pair is stored as most once.
class CollisionList : public std::vector<CollisionPair> {
public:
void push_back(CollisionPair p) {
// only add a pair if it's not already in there
for(iterator i=begin(); i!=end(); i++) {
if((*i)==p) return;
}
std::vector<CollisionPair>::push_back(p);
}; // push_back
};
CollisionList m_all_collisions;
void KartKartCollision(Kart *ka, Kart *kb);
public:
void convertTrack (ssgEntity *track, sgMat4 m, btTriangleMesh* track_mesh);
Physics (float gravity);
~Physics ();
void addKart (const Kart *k, btRaycastVehicle *v);
@ -46,30 +93,21 @@ public:
void removeKart (const Kart *k);
void removeBody (btRigidBody* b) {m_dynamics_world->removeRigidBody(b);}
void update (float dt);
void handleCollisions();
void draw ();
void setTrack (ssgEntity *track);
btDynamicsWorld*
getPhysicsWorld () const {return m_dynamics_world;}
void debugDraw (float m[16], btCollisionShape *s, const btVector3 color);
static float NOHIT;
static const float NOHIT;
float getHAT (btVector3 pos);
bool getTerrainNormal(btVector3 pos, btVector3* normal);
virtual btScalar solveGroup(btCollisionObject** bodies, int numBodies,
btPersistentManifold** manifold,int numManifolds,
btTypedConstraint** constraints,int numConstraints,
const btContactSolverInfo& info,
btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc,
btDispatcher* dispatcher);
};
// For non-bullet version: empty object
#else
class Physics
{
public:
Physics(float gravity) {};
~Physics() {};
void update(float dt) {};
void setTrack(ssgEntity *track) {};
void draw () {};
};
#endif
#endif
/* EOF */

View File

@ -147,7 +147,7 @@ void PlayerKart::update(float dt)
m_collectable.use() ;
m_controls.fire = false;
}
if ( isOnGround() && m_controls.rescue )
if ( m_controls.rescue )
{
sound_manager -> playSfx ( SOUND_BEEP ) ;
forceRescue();

View File

@ -19,7 +19,9 @@
#include "loader.hpp"
#include "projectile_manager.hpp"
#include "projectile.hpp"
#include "spark.hpp"
#include "missile.hpp"
#include "homing.hpp"
#include "explosion.hpp"
#include "collectable_manager.hpp"
#include "collectable.hpp"
@ -50,7 +52,7 @@ void ProjectileManager::removeTextures()
{
cleanup();
ssgDeRefDelete(m_explosion_model);
// Only the explosion is here, all other models are actualy managed
// Only the explosion is here, all other models are actually managed
// by collectable_manager.
callback_manager->clear(CB_EXPLOSION);
} // removeTextures
@ -61,7 +63,7 @@ void ProjectileManager::cleanup()
for(Projectiles::iterator i = m_active_projectiles.begin();
i != m_active_projectiles.end(); ++i)
{
ssgTransform *m = (*i)->getModel();
ssgTransform *m = (*i)->getModelTransform();
m->removeAllKids();
delete *i;
}
@ -93,12 +95,10 @@ void ProjectileManager::update(float dt)
{
if(! (*p)->hasHit()) { p++; continue; }
newExplosion((*p)->getCoord());
// Create a new explosion, move the projectile to the
// list of deleted projectiles (so that they can be
// reused later), and remove it from the list of active
// projectiles.
m_deleted_projectiles.push_back(*p);
p=m_active_projectiles.erase(p); // returns the next element
Flyable *f=*p;
Projectiles::iterator pNext=m_active_projectiles.erase(p); // returns the next element
delete f;
p=pNext;
} // while p!=m_active_projectiles.end()
}
@ -115,32 +115,27 @@ void ProjectileManager::update(float dt)
while(e!=m_active_explosions.end())
{
if(!(*e)->hasEnded()) { e++; continue;}
m_deleted_explosions.push_back(*e);
e=m_active_explosions.erase(e);
Explosion *exp=*e;
Explosions::iterator eNext=m_active_explosions.erase(e);
ssgDeRefDelete(exp); // reduce refcount and free object
e=eNext;
} // while e!=m_active_explosions.end()
} // if m_explosion_ended
m_something_was_hit=false;
} // update
// -----------------------------------------------------------------------------
/** See if there is an old, unused projectile object available. If so,
* reuse this object, otherwise create a new one. */
Projectile *ProjectileManager::newProjectile(Kart *kart, int type)
Flyable *ProjectileManager::newProjectile(Kart *kart, CollectableType type)
{
Projectile *p;
if(m_deleted_projectiles.size()>0)
{
p = m_deleted_projectiles.back();
m_deleted_projectiles.pop_back();
p->init(kart, type);
Flyable *f;
switch(type) {
case COLLECT_SPARK: f = new Spark(kart); break;
case COLLECT_HOMING: f = new Homing(kart); break;
case COLLECT_MISSILE: f = new Missile(kart); break;
default: return NULL;
}
else
{
p=new Projectile(kart, type);
}
m_active_projectiles.push_back(p);
return p;
m_active_projectiles.push_back(f);
return f;
} // newProjectile
// -----------------------------------------------------------------------------
@ -148,17 +143,7 @@ Projectile *ProjectileManager::newProjectile(Kart *kart, int type)
* reuse this object, otherwise create a new one. */
Explosion* ProjectileManager::newExplosion(sgCoord* coord)
{
Explosion *e;
if(m_deleted_explosions.size()>0)
{
e = m_deleted_explosions.back();
m_deleted_explosions.pop_back();
e->init(coord);
}
else
{
e=new Explosion(coord);
}
Explosion *e = new Explosion(coord);
m_active_explosions.push_back(e);
return e;
} // newExplosion

View File

@ -22,34 +22,26 @@
#include <vector>
#include <plib/ssg.h>
#include "flyable.hpp"
#include "collectable_manager.hpp"
class Kart;
class Projectile;
class Explosion;
class ProjectileManager
{
private:
typedef std::vector<Projectile*> Projectiles;
typedef std::vector<Flyable*> Projectiles;
typedef std::vector<Explosion* > Explosions;
// The list of all active projectiles, i.e. projectiles
// which are currently moving on the track
Projectiles m_active_projectiles;
// The list of all deleted projectiles, i.e. projectils which
// hit something and have therefore been deleted. The objects
// in this list can be reused later, this removes the overhead
// of object creation
Projectiles m_deleted_projectiles;
// All active explosions, i.e. explosions which are currently
// being shown
Explosions m_active_explosions;
// The list of deleted explosion, which will be reused.
Explosions m_deleted_explosions;
ssgSelector* m_explosion_model;
bool m_something_was_hit;
bool m_explosion_ended;
@ -67,9 +59,9 @@ public:
void loadData ();
void cleanup ();
void update (float dt);
Projectile* newProjectile (Kart *kart, int type);
Flyable* newProjectile (Kart *kart, CollectableType type);
Explosion* newExplosion (sgCoord *coord);
void Deactivate (Projectile *p) {}
void Deactivate (Flyable *p) {}
void removeTextures ();
};

View File

@ -326,7 +326,7 @@ void DefaultRobot::handle_items( const float DELTA, const int STEPS )
break;
case COLLECT_MISSILE:
case COLLECT_HOMING_MISSILE:
case COLLECT_HOMING:
if( m_time_since_last_shot > 5.0f && m_crashes.m_kart != -1 )
{
if( sgDistanceVec2( m_curr_pos.xyz,

View File

@ -65,6 +65,7 @@ SoundManager::SoundManager()
}
else
m_initialized = true;
getcwd
#else
if(alutInit(0, NULL) == AL_TRUE) // init OpenAL sound system
m_initialized = true;

View File

@ -197,8 +197,12 @@ void UserConfig::setDefaults()
set(GA_LEAVE_RACE,
Input(IT_KEYBOARD, SDLK_ESCAPE));
set(GA_DEBUG_ADD_SPARK,
Input(IT_KEYBOARD, SDLK_F1));
set(GA_DEBUG_ADD_MISSILE,
Input(IT_KEYBOARD, SDLK_F7));
Input(IT_KEYBOARD, SDLK_F2));
set(GA_DEBUG_ADD_HOMING,
Input(IT_KEYBOARD, SDLK_F3));
set(GA_DEBUG_TOGGLE_FPS,
Input(IT_KEYBOARD, SDLK_F12));
set(GA_DEBUG_TOGGLE_WIREFRAME,
@ -206,7 +210,7 @@ void UserConfig::setDefaults()
set(GA_DEBUG_HISTORY,
Input(IT_KEYBOARD, SDLK_F10));
set(GA_DEBUG_BULLET,
Input(IT_KEYBOARD, SDLK_F2));
Input(IT_KEYBOARD, SDLK_F4));
// TODO: The following should become a static
// array. This allows:

View File

@ -1,37 +0,0 @@
// $Id$
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2004 Steve Baker <sjbaker1@airmail.net>
//
// 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.
#include <plib/sg.h>
void pr_from_normal ( sgVec3 hpr, sgVec3 nrm )
{
const float SY = sin ( -hpr [ 0 ] * SG_DEGREES_TO_RADIANS ) ;
const float CY = cos ( -hpr [ 0 ] * SG_DEGREES_TO_RADIANS ) ;
hpr[2] = SG_RADIANS_TO_DEGREES * atan2 ( nrm[0] * CY - nrm[1] * SY, nrm[2] ) ;
hpr[1] = -SG_RADIANS_TO_DEGREES * atan2 ( nrm[1] * CY + nrm[0] * SY, nrm[2] ) ;
}
//-----------------------------------------------------------------------------
void hpr_from_normal ( sgVec3 hpr, sgVec3 nrm )
{
pr_from_normal ( hpr, nrm ) ;
hpr[0] = -SG_RADIANS_TO_DEGREES * atan2 ( nrm[0], nrm[1] ) ;
}

View File

@ -1,26 +0,0 @@
// $Id$
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2004 Steve Baker <sjbaker1@airmail.net>
//
// 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_UTILS_H
#define HEADER_UTILS_H
//FIXME: erase this file or put what should go here?
#endif

View File

@ -102,9 +102,6 @@ World::World(const RaceSetup& raceSetup_) : m_race_setup(raceSetup_)
assert(m_race_setup.m_karts.size() > 0);
// Clear all callbacks, which might still be stored there from a previous race.
callback_manager->clear(CB_TRACK);
// Load the track models - this must be done before the karts so that the
// karts can be positioned properly on (and not in) the tracks.
loadTrack ( ) ;
@ -118,7 +115,6 @@ World::World(const RaceSetup& raceSetup_) : m_race_setup(raceSetup_)
{
sgCoord init_pos;
m_track->getStartCoords(pos, &init_pos);
Kart* newkart;
if(user_config->m_profile)
{
@ -149,9 +145,9 @@ World::World(const RaceSetup& raceSetup_) : m_race_setup(raceSetup_)
{
history->LoadKartData(newkart, pos);
}
newkart -> getModel () -> clrTraversalMaskBits(SSGTRAV_ISECT|SSGTRAV_HOT);
newkart -> getModelTransform() -> clrTraversalMaskBits(SSGTRAV_ISECT|SSGTRAV_HOT);
scene->add ( newkart -> getModel() ) ;
scene->add ( newkart -> getModelTransform() ) ;
m_kart.push_back(newkart);
pos++;
} // for i
@ -201,7 +197,7 @@ World::World(const RaceSetup& raceSetup_) : m_race_setup(raceSetup_)
}
if( m_p_replay_player ) m_p_replay_player->showReplayAt( 0.0 );
#endif
}
} // World
//-----------------------------------------------------------------------------
World::~World()
@ -210,6 +206,9 @@ World::~World()
saveReplayHumanReadable( "test" );
#endif
// Clear all callbacks
callback_manager->clear(CB_TRACK);
for ( unsigned int i = 0 ; i < m_kart.size() ; i++ )
delete m_kart[i];
@ -253,7 +252,7 @@ void World::resetAllKarts()
{
#ifdef BULLET
bool all_finished=false;
for(int i=0; i<10; i++) m_physics->update(1./60.);
for(int i=0; i<10; i++) m_physics->update(1.f/60.f);
while(!all_finished)
{
m_physics->update(1.f/60.f);

View File

@ -102,9 +102,9 @@ public:
float getGravity() const { return m_track->getGravity(); }
Physics *getPhysics() const { return m_physics; }
Track *getTrack() const { return m_track; }
#ifdef BULLET
float getHAT(btVector3 pos) const { return m_physics->getHAT(pos); }
#endif
bool getTerrainNormal(btVector3 pos, btVector3 *nrm)
const { return m_physics->getTerrainNormal(pos,nrm);}
Kart* getFastestKart() const { return m_fastest_kart; }
float getFastestLapTime() const { return m_fastest_lap; }
void setFastestLap(Kart *k, float time) {m_fastest_kart=k;m_fastest_lap=time;}