1
// $Id: World.cxx 498 2004-12-22 06:55:12Z grumbel $
3
// SuperTuxKart - a fun racing game with go-kart
4
// Copyright (C) 2004 Steve Baker <sjbaker1@airmail.net>
6
// This program is free software; you can redistribute it and/or
7
// modify it under the terms of the GNU General Public License
8
// as published by the Free Software Foundation; either version 2
9
// of the License, or (at your option) any later version.
11
// This program is distributed in the hope that it will be useful,
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
// GNU General Public License for more details.
16
// You should have received a copy of the GNU General Public License
17
// along with this program; if not, write to the Free Software
18
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25
#include "preprocessor.h"
26
#include "Explosion.h"
28
#include "Projectile.h"
29
#include "KartDriver.h"
30
#include "WidgetSet.h"
36
#include "RaceSetup.h"
37
#include "WorldLoader.h"
38
#include "PlayerDriver.h"
39
#include "AutoDriver.h"
42
#include "KartManager.h"
43
#include "TrackManager.h"
47
World::World(const RaceSetup& raceSetup_)
48
: raceSetup(raceSetup_)
57
// Grab the track centerline file
58
track = track_manager->getTrack(raceSetup.track) ;
60
// Start building the scene graph
62
trackBranch = new ssgBranch ;
63
scene -> addKid ( trackBranch ) ;
65
/* Load the Herring */
66
sgVec3 yellow = { 1.0, 1.0, 0.4 } ;
68
gold_h = new Herring ( yellow ) ;
69
silver_h = new Herring ( ssgLoad ( "coin.ac", loader ) ) ;
70
red_h = new Herring ( ssgLoad ( "bonusblock.ac", loader ) ) ;
71
green_h = new Herring ( ssgLoad ( "banana.ac", loader ) ) ;
73
preProcessObj ( gold_h -> getRoot());
74
preProcessObj ( silver_h -> getRoot());
75
preProcessObj ( red_h -> getRoot());
76
preProcessObj ( green_h -> getRoot());
78
// Create the karts and fill the kart vector with them
80
assert(raceSetup.karts.size() > 0);
82
for (RaceSetup::Karts::iterator i = raceSetup.karts.begin() ; i != raceSetup.karts.end() ; ++i )
85
int pos = kart.size();
87
if (std::find(raceSetup.players.begin(), raceSetup.players.end(), pos) != raceSetup.players.end())
88
{ // the given position belongs to a player
89
newkart = new KartDriver ( this, kart_manager.getKart(*i), pos, new PlayerDriver ) ;
92
newkart = new KartDriver ( this, kart_manager.getKart(*i), pos, new AutoDriver ) ;
94
sgCoord init_pos = { { 0, 0, 0 }, { 0, 0, 0 } } ;
96
init_pos.xyz [ 0 ] = (pos % 2 == 0) ? 1.5f : -1.5f ;
97
init_pos.xyz [ 1 ] = -pos * 1.5f ;
99
newkart -> setReset ( & init_pos ) ;
100
newkart -> reset () ;
101
newkart -> getModel () -> clrTraversalMaskBits(SSGTRAV_ISECT|SSGTRAV_HOT);
103
scene -> addKid ( newkart -> getRoot() ) ;
105
kart.push_back(newkart);
108
// Load the track models
112
preProcessObj ( scene ) ;
114
#ifdef SSG_BACKFACE_COLLISIONS_SUPPORTED
115
//ssgSetBackFaceCollisions ( raceSetup.mirror ) ;
118
guiStack.push_back(GUIS_RACE);
120
std::string music = track_manager->getTrack(raceSetup.track)->music_filename;
123
sound -> change_track ( music.c_str() );
130
for ( unsigned int i = 0 ; i < kart.size() ; i++ )
135
for(Projectiles::iterator i = projectiles.begin();
136
i != projectiles.end(); ++i)
138
for(Explosions::iterator i = explosions.begin(); i != explosions.end(); ++i)
141
ssgDeRefDelete(projectile_spark);
142
ssgDeRefDelete(projectile_missle);
143
ssgDeRefDelete(projectile_flamemissle);
144
ssgDeRefDelete(explode);
157
for ( Karts::size_type i = 0 ; i < kart.size(); ++i) kart[ i ] -> placeModel() ;
159
ssgGetLight ( 0 ) -> setPosition ( track->sun_position ) ;
160
ssgGetLight ( 0 ) -> setColour ( GL_AMBIENT , track->ambientcol ) ;
161
ssgGetLight ( 0 ) -> setColour ( GL_DIFFUSE , track->diffusecol ) ;
162
ssgGetLight ( 0 ) -> setColour ( GL_SPECULAR, track->specularcol ) ;
164
ssgCullAndDraw ( world->scene ) ;
168
World::update(float delta)
174
for ( Karts::size_type i = 0 ; i < kart.size(); ++i) kart[ i ] -> update (delta) ;
175
for(Projectiles::iterator i = projectiles.begin();
176
i != projectiles.end(); ++i)
178
for(Explosions::iterator i = explosions.begin(); i != explosions.end(); ++i)
180
for ( int i = 0 ; i < MAX_HERRING ; i++ ) herring [ i ] . update () ;
181
for ( Karts::size_type i = 0 ; i < kart.size(); ++i) updateLapCounter ( i ) ;
183
/* Routine stuff we do even when paused */
184
silver_h -> update () ;
185
gold_h -> update () ;
187
green_h -> update () ;
191
World::checkRaceStatus()
193
if (clock > 1.0 && ready_set_go == 0)
197
else if (clock > 2.0 && ready_set_go == 1)
203
else if (clock > 1.0 && ready_set_go == 2)
207
else if (clock > 0.0 && ready_set_go == 3)
212
if ( world->kart[0]->getLap () >= raceSetup.numLaps )
214
phase = FINISH_PHASE;
219
World::updateLapCounter ( int k )
223
/* Find position of kart 'k' */
225
for ( Karts::size_type j = 0 ; j < kart.size() ; ++j )
227
if ( int(j) == k ) continue ;
229
if ( kart[j]->getLap() > kart[k]->getLap() ||
230
( kart[j]->getLap() == kart[k]->getLap() &&
231
kart[j]->getDistanceDownTrack() >
232
kart[k]->getDistanceDownTrack() ))
236
kart [ k ] -> setPosition ( p ) ;
242
for ( Karts::size_type i = 0 ; i < kart.size() ; ++i )
244
kart[i]->load_data();
247
projectile_spark = ssgLoad("spark.ac");
248
projectile_spark->ref();
249
projectile_missle = ssgLoad("missile.ac");
250
projectile_missle->ref();
251
projectile_flamemissle = ssgLoad("flamemissile.ac");
252
projectile_flamemissle->ref();
253
explode = ssgLoad("explode.ac");
258
World::herring_command (char *s, char *str )
260
if ( num_herring >= MAX_HERRING )
262
fprintf ( stderr, "Too many herring\n" ) ;
266
HerringInstance *h = & herring[num_herring] ;
269
sscanf ( s, "%f,%f", &xyz[0], &xyz[1] ) ;
271
xyz[2] = 1000000.0f ;
272
xyz[2] = getHeight ( trackBranch, xyz ) + 0.06 ;
276
sgSetVec3 ( c.hpr, 0.0f, 0.0f, 0.0f ) ;
277
sgCopyVec3 ( c.xyz, xyz ) ;
279
if ( str[0]=='Y' || str[0]=='y' ){ h->her = gold_h ; h->type = HE_GOLD ;}
280
if ( str[0]=='G' || str[0]=='g' ){ h->her = green_h ; h->type = HE_GREEN ;}
281
if ( str[0]=='R' || str[0]=='r' ){ h->her = red_h ; h->type = HE_RED ;}
282
if ( str[0]=='S' || str[0]=='s' ){ h->her = silver_h ; h->type = HE_SILVER ;}
284
sgCopyVec3 ( h->xyz, xyz ) ;
286
h->scs = new ssgTransform ;
287
h->scs -> setTransform ( &c ) ;
288
h->scs -> addKid ( h->her->getRoot () ) ;
289
scene -> addKid ( h->scs ) ;
298
std::string path = "data/";
299
path += track->getIdent();
301
path = loader->getPath(path);
302
FILE *fd = fopen (path.c_str(), "r" ) ;
306
std::stringstream msg;
307
msg << "Can't open track location file '" << path << "'.";
308
throw std::runtime_error(msg.str());
315
while ( fgets ( s, 1023, fd ) != NULL )
317
if ( *s == '#' || *s < ' ' )
320
int need_hat = FALSE ;
321
int fit_skin = FALSE ;
322
char fname [ 1024 ] ;
324
sgZeroVec3 ( loc.xyz ) ;
325
sgZeroVec3 ( loc.hpr ) ;
329
if ( sscanf ( s, "%cHERRING,%f,%f", &htype,
330
&(loc.xyz[0]), &(loc.xyz[1]) ) == 3 )
332
herring_command ( & s [ strlen ( "*HERRING," ) ], s ) ;
337
if ( sscanf ( s, "\"%[^\"]\",%f,%f,%f,%f,%f,%f",
338
fname, &(loc.xyz[0]), &(loc.xyz[1]), &(loc.xyz[2]),
339
&(loc.hpr[0]), &(loc.hpr[1]), &(loc.hpr[2]) ) == 7 )
341
/* All 6 DOF specified */
345
if ( sscanf ( s, "\"%[^\"]\",%f,%f,{},%f,%f,%f",
346
fname, &(loc.xyz[0]), &(loc.xyz[1]),
347
&(loc.hpr[0]), &(loc.hpr[1]), &(loc.hpr[2]) ) == 6 )
349
/* All 6 DOF specified - but need height */
353
if ( sscanf ( s, "\"%[^\"]\",%f,%f,%f,%f",
354
fname, &(loc.xyz[0]), &(loc.xyz[1]), &(loc.xyz[2]),
355
&(loc.hpr[0]) ) == 5 )
357
/* No Roll/Pitch specified - assumed zero */
361
if ( sscanf ( s, "\"%[^\"]\",%f,%f,{},%f,{},{}",
362
fname, &(loc.xyz[0]), &(loc.xyz[1]), &(loc.hpr[0]) ) == 3 )
364
/* All 6 DOF specified - but need height, roll, pitch */
369
if ( sscanf ( s, "\"%[^\"]\",%f,%f,{},%f",
370
fname, &(loc.xyz[0]), &(loc.xyz[1]),
371
&(loc.hpr[0]) ) == 4 )
373
/* No Roll/Pitch specified - but need height */
377
if ( sscanf ( s, "\"%[^\"]\",%f,%f,%f",
378
fname, &(loc.xyz[0]), &(loc.xyz[1]), &(loc.xyz[2]) ) == 4 )
380
/* No Heading/Roll/Pitch specified - but need height */
384
if ( sscanf ( s, "\"%[^\"]\",%f,%f,{}",
385
fname, &(loc.xyz[0]), &(loc.xyz[1]) ) == 3 )
387
/* No Roll/Pitch specified - but need height */
391
if ( sscanf ( s, "\"%[^\"]\",%f,%f",
392
fname, &(loc.xyz[0]), &(loc.xyz[1]) ) == 3 )
394
/* No Z/Heading/Roll/Pitch specified */
398
if ( sscanf ( s, "\"%[^\"]\"", fname ) == 1 )
400
/* Nothing specified */
406
std::stringstream msg;
407
msg << "Syntax error in '" << path << "': " << s;
408
throw std::runtime_error(msg.str());
415
loc.xyz[2] = 1000.0f ;
416
loc.xyz[2] = getHeightAndNormal ( trackBranch, loc.xyz, nrm ) ;
420
float sy = sin ( -loc.hpr [ 0 ] * SG_DEGREES_TO_RADIANS ) ;
421
float cy = cos ( -loc.hpr [ 0 ] * SG_DEGREES_TO_RADIANS ) ;
423
loc.hpr[2] = SG_RADIANS_TO_DEGREES * atan2 ( nrm[0] * cy -
424
nrm[1] * sy, nrm[2] ) ;
425
loc.hpr[1] = -SG_RADIANS_TO_DEGREES * atan2 ( nrm[1] * cy +
426
nrm[0] * sy, nrm[2] ) ;
430
ssgEntity *obj = ssgLoad ( fname, loader ) ;
431
ssgRangeSelector *lod = new ssgRangeSelector ;
432
ssgTransform *trans = new ssgTransform ( & loc ) ;
434
float r [ 2 ] = { -10.0f, 2000.0f } ;
436
lod -> addKid ( obj ) ;
437
trans -> addKid ( lod ) ;
438
trackBranch -> addKid ( trans ) ;
439
lod -> setRanges ( r, 2 ) ;
444
std::stringstream msg;
445
msg << "Syntax error in '" << path << "': " << s;
446
throw std::runtime_error(msg.str());
457
finishing_position = -1 ;
461
for ( Karts::iterator i = kart.begin(); i != kart.end() ; ++i )
466
World::getKart(int kartId)
468
assert(kartId >= 0 && kartId < int(kart.size()));
473
World::getPlayerKart(int player)
475
return kart[raceSetup.players[player]];