Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/trunk/src/story_entities/world.cc @ 4976

Last change on this file since 4976 was 4976, checked in by bensch, 19 years ago

orxonox/trunk: flotilia

File size: 29.7 KB
Line 
1
2
3/*
4   orxonox - the future of 3D-vertical-scrollers
5
6   Copyright (C) 2004 orx
7
8   This program is free software; you can redistribute it and/or modify
9   it under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 2, or (at your option)
11   any later version.
12
13   ### File Specific:
14   main-programmer: Patrick Boenzli
15   co-programmer: Christian Meyer
16*/
17
18#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_WORLD
19
20#include "world.h"
21
22#include "orxonox.h"
23
24#include "state.h"
25
26#include "p_node.h"
27#include "null_parent.h"
28#include "pilot_node.h"
29#include "track_node.h"
30#include "world_entity.h"
31#include "player.h"
32#include "camera.h"
33#include "environment.h"
34#include "skysphere.h"
35#include "skybox.h"
36#include "satellite.h"
37#include "test_entity.h"
38#include "terrain.h"
39#include "light.h"
40#include "text_engine.h"
41#include "load_param.h"
42
43#include "track_manager.h"
44#include "garbage_collector.h"
45#include "fast_factory.h"
46#include "animation_player.h"
47#include "particle_engine.h"
48#include "graphics_engine.h"
49#include "physics_engine.h"
50#include "fields.h"
51
52#include "md2Model.h"
53
54#include "glmenu_imagescreen.h"
55#include "list.h"
56#include "game_loader.h"
57
58#include "animation3d.h"
59
60#include "substring.h"
61
62#include "factory.h"
63
64#include "projectile.h"
65#include "event_handler.h"
66
67#include "sound_engine.h"
68#include "ogg_player.h"
69
70#include "class_list.h"
71
72#include "cd_engine.h"
73#include "npc.h"
74
75using namespace std;
76
77WorldInterface* WorldInterface::singletonRef = 0;
78
79
80/**
81 *  private constructor because of singleton
82*/
83WorldInterface::WorldInterface()
84{
85  this->worldIsInitialized = false;
86  this->worldReference = NULL;
87}
88
89/**
90 *  public deconstructor
91*/
92WorldInterface::~WorldInterface()
93{
94  this->singletonRef = NULL;
95  this->worldIsInitialized = false;
96  this->worldReference = NULL;
97}
98
99/**
100 *  gets the singleton instance
101 * @returns singleton instance
102*/
103WorldInterface* WorldInterface::getInstance()
104{
105  if( singletonRef == NULL)
106    singletonRef = new WorldInterface();
107  return singletonRef;
108}
109
110
111/**
112 *  initializes the interface
113 * @param reference to the world
114
115   if the worldinterface is not initilizes, there wont be any
116   useable interface
117*/
118void WorldInterface::init(World* world)
119{
120  this->worldReference = world;
121  if( world != NULL)
122    {
123      this->worldIsInitialized = true;
124      PRINTF(3)("WorldInterface up and running\n");
125    }
126}
127
128
129/**
130 *  gets the entity list from the world
131 * @return entity list
132*/
133tList<WorldEntity>* WorldInterface::getEntityList()
134{
135  if( this->worldIsInitialized)
136    return this->worldReference->getEntities();
137  PRINT(1)("tried to use the WorldInterface before it has been initizlized! this can result in SEGFAULTs!\n");
138  return NULL;
139}
140
141CREATE_FACTORY(World);
142
143World::World(const TiXmlElement* root)
144{
145  this->constuctorInit("", -1);
146  this->path = NULL;
147
148  this->loadParams(root);
149}
150
151/**
152  *  create a new World
153
154    This creates a new empty world!
155*/
156World::World (char* name)
157{
158  this->path = NULL;
159  this->constuctorInit(name, -1);
160  //NullParent* np = NullParent::getInstance();
161}
162
163/**
164 *  creates a new World...
165 * @param worldID with this ID
166*/
167World::World (int worldID)
168{
169  this->path = NULL;
170  this->constuctorInit(NULL, worldID);
171}
172
173/**
174 *  remove the World from memory
175
176    delete everything explicitly, that isn't contained in the parenting tree!
177    things contained in the tree are deleted automaticaly
178 */
179World::~World ()
180{
181  PRINTF(3)("World::~World() - deleting current world\n");
182
183  ParticleEngine::getInstance()->debug();
184
185  delete WorldInterface::getInstance();
186  delete this->entities;
187  State::setWorldEntityList(NULL);
188//  delete NullParent::getInstance();
189
190
191  delete LightManager::getInstance();
192  delete TrackManager::getInstance();
193  delete ParticleEngine::getInstance();
194
195  TextEngine::getInstance()->flush();
196  SoundEngine::getInstance()->flushAllBuffers();
197  SoundEngine::getInstance()->flushAllSources();
198
199  delete AnimationPlayer::getInstance(); // this should be at the end of the unloading sequence.
200  delete PhysicsEngine::getInstance();
201  //delete garbagecollecor
202  //delete animator
203
204  FastFactory::flushAll();
205  delete NullParent::getInstance();
206  EventHandler::getInstance()->debug();
207
208  LoadClassDescription::printAll();
209
210
211  ResourceManager::getInstance()->unload(this->music);
212  ResourceManager::getInstance()->unloadAllByPriority(RP_LEVEL);
213}
214
215/**
216 *  initializes the world.
217
218   set all stuff here that is world generic and does not use to much memory
219   because the real init() function StoryEntity::init() will be called
220   shortly before start of the game.
221   since all worlds are initiated/referenced before they will be started.
222   NO LEVEL LOADING HERE - NEVER!
223*/
224void World::constuctorInit(char* name, int worldID)
225{
226  this->setClassID(CL_WORLD, "World");
227
228  //this->worldName = name;
229  //this->worldName = new char[strlen(name)+1];
230  //strcpy(this->worldName, name);
231  this->debugWorldNr = worldID;
232
233  this->music = NULL;
234}
235
236void World::loadParams(const TiXmlElement* root)
237{
238  const char *string;
239  char *name;
240  int id;
241
242  PRINTF(4)("Creating a World\n");
243
244  LoadParam<World>(root, "identifier", this, &World::setStoryID)
245    .describe("Sets the StoryID of this world");
246
247  LoadParam<World>(root, "nextid", this, &World::setNextStoryID)
248    .describe("Sets the ID of the next world");
249
250  LoadParam<World>(root, "path", this, &World::setPath)
251    .describe("The Filename of this World (relative from the data-dir)");
252}
253
254
255/**
256 *  this is executed before load
257
258   since the load function sometimes needs data, that has been init before
259   the load and after the proceeding storyentity has finished
260*/
261ErrorMessage World::preLoad()
262{
263  State::setWorldEntityList(this->entities = new tList<WorldEntity>());
264  this->cycle = 0;
265
266
267  /* init the world interface */
268  WorldInterface* wi = WorldInterface::getInstance();
269  wi->init(this);
270
271  LightManager::getInstance();
272  this->nullParent = NullParent::getInstance ();
273  this->nullParent->setName ("NullParent");
274
275  AnimationPlayer::getInstance(); // initializes the animationPlayer
276  PhysicsEngine::getInstance();
277
278  this->localCamera = new Camera();
279  this->localCamera->setName ("Camera");
280
281  State::setCamera(this->localCamera, this->localCamera->getTarget());
282
283  GraphicsEngine::getInstance()->displayFPS(true);
284
285  CDEngine::getInstance()->setEntityList( this->entities);
286}
287
288
289/**
290 *  loads the World by initializing all resources, and set their default values.
291*/
292ErrorMessage World::load()
293{
294  PRINTF(3)("> Loading world: '%s'\n", getPath());
295  TiXmlElement* element;
296  GameLoader* loader = GameLoader::getInstance();
297
298  if( getPath() == NULL)
299    {
300      PRINTF(1)("World has no path specified for loading");
301      this->loadDebugWorld(this->getStoryID());
302      return (ErrorMessage){213,"Path not specified","World::load()"};
303    }
304
305  TiXmlDocument* XMLDoc = new TiXmlDocument( path);
306  // load the campaign document
307  if( !XMLDoc->LoadFile())
308  {
309    // report an error
310    PRINTF(1)("loading XML File: %s @ %d:%d\n", XMLDoc->ErrorDesc(), XMLDoc->ErrorRow(), XMLDoc->ErrorCol());
311    delete XMLDoc;
312    return (ErrorMessage){213,"XML File parsing error","World::load()"};
313  }
314
315  // check basic validity
316  TiXmlElement* root = XMLDoc->RootElement();
317  assert( root != NULL);
318
319  if( root == NULL || root->Value() == NULL || strcmp( root->Value(), "WorldDataFile"))
320    {
321      // report an error
322      PRINTF(1)("Specified XML File is not an orxonox world data file (WorldDataFile element missing)\n");
323      delete XMLDoc;
324      return (ErrorMessage){213,"Path not a WorldDataFile","World::load()"};
325    }
326
327  // load the parameters
328  // name
329  char* temp;
330  const char* string = grabParameter( root, "name");
331  if( string == NULL)
332    {
333      PRINTF(2)("World is missing a proper 'name'\n");
334      string = "Unknown";
335      temp = new char[strlen(string + 2)];
336      strcpy( temp, string);
337      this->worldName = temp;
338    }
339  else
340    {
341      temp = new char[strlen(string + 2)];
342      strcpy( temp, string);
343      this->worldName = temp;
344    }
345  ////////////////
346  // LOADSCREEN //
347  ////////////////
348  element = root->FirstChildElement("LoadScreen");
349  if (element == NULL)
350    {
351      PRINTF(2)("no LoadScreen specified, loading default\n");
352
353      glmis->setBackgroundImage("pictures/load_screen.jpg");
354      this->glmis->setMaximum(8);
355      this->glmis->draw();
356    }
357  else
358    {
359      this->glmis->loadParams(element);
360      this->glmis->draw();
361    }
362  this->glmis->draw();
363
364  ////////////////////////
365  // find WorldEntities //
366  ////////////////////////
367
368  element = root->FirstChildElement("WorldEntities");
369
370  if( element == NULL)
371    {
372      PRINTF(1)("World is missing 'WorldEntities'\n");
373    }
374  else
375    {
376      element = element->FirstChildElement();
377      // load Players/Objects/Whatever
378      PRINTF(4)("Loading WorldEntities\n");
379      while( element != NULL)
380        {
381          WorldEntity* created = dynamic_cast<WorldEntity*>( loader->fabricate( element));
382          if( created != NULL) this->spawn( created);
383          // if we load a 'Player' we use it as localPlayer
384          //todo do this more elegant
385          if( element->Value() != NULL && !strcmp( element->Value(), "Player"))
386          {
387            localPlayer = (Player*) created;
388            CDEngine::getInstance()->setPlayer(localPlayer);
389          }
390          if( element->Value() != NULL && !strcmp( element->Value(), "SkyBox")) sky = (SkyBox*) created;
391          if( element->Value() != NULL && !strcmp( element->Value(), "Terrain"))
392          {
393            terrain = (Terrain*) created;
394            CDEngine::getInstance()->setTerrain(terrain);
395          }
396          element = element->NextSiblingElement();
397          glmis->step(); //! @todo temporary
398        }
399      PRINTF(4)("Done loading WorldEntities\n");
400    }
401
402    //////////////////////////////
403    // LOADING ADDITIONAL STUFF //
404    //////////////////////////////
405
406    LoadParam<LightManager>(root, "LightManager", LightManager::getInstance(), &LightManager::loadParams);
407
408    LoadParam<ParticleEngine>(root, "ParticleEngine", ParticleEngine::getInstance(), &ParticleEngine::loadParams);
409    LoadParam<PhysicsEngine>(root, "PhysicsEngine", PhysicsEngine::getInstance(), &PhysicsEngine::loadParams);
410
411  // find Track
412  element = root->FirstChildElement( "Track");
413  if( element == NULL)
414    {
415      PRINTF(0)("World is missing a 'Track'\n");
416    }
417  else
418    {
419      //load track
420      PRINTF(4)("Loading Track\n");
421
422      TrackManager::getInstance()->loadParams( element);
423      TrackManager::getInstance()->finalize();
424    }
425
426  // free the XML data
427
428  delete XMLDoc;
429  /* GENERIC LOADING PROCESS FINISHED */
430
431  // bind input
432  EventHandler::getInstance()->subscribe(this->localPlayer, ES_GAME, KeyMapper::PEV_UP);
433  EventHandler::getInstance()->subscribe(this->localPlayer, ES_GAME, KeyMapper::PEV_DOWN);
434  EventHandler::getInstance()->subscribe(this->localPlayer, ES_GAME, KeyMapper::PEV_LEFT);
435  EventHandler::getInstance()->subscribe(this->localPlayer, ES_GAME, KeyMapper::PEV_RIGHT);
436  EventHandler::getInstance()->subscribe(this->localPlayer, ES_GAME, KeyMapper::PEV_FIRE1);
437  EventHandler::getInstance()->subscribe(this->localPlayer, ES_GAME, KeyMapper::PEV_NEXT_WEAPON);
438  EventHandler::getInstance()->subscribe(this->localPlayer, ES_GAME, KeyMapper::PEV_PREVIOUS_WEAPON);
439
440  // bind camera
441  //this->localCamera->bind (localPlayer);
442 // this->localPlayer->addChild (this->localCamera);
443
444
445//   lightMan->setAmbientColor(.1,.1,.1);
446//   lightMan->addLight();
447//   //      lightMan->setAttenuation(1.0, .01, 0.0);
448//   //      lightMan->setDiffuseColor(1,1,1);
449//   //  lightMan->addLight(1);
450//   //  lightMan->setPosition(20, 10, -20);
451//   //  lightMan->setDiffuseColor(0,0,0);
452//   //lightMan->debug();
453//   lightMan->setPosition(-5.0, 50.0, -40.0);
454//   lightMan->addLight();
455//   lightMan->setPosition(100, 80, 60);
456
457  //        TrackManager::getInstance()->setBindSlave(env);
458  PNode* tn = TrackManager::getInstance()->getTrackNode();
459  tn->addChild(this->localPlayer);
460
461  //localCamera->setParent(TrackNode::getInstance());
462  tn->addChild(this->localCamera);
463  localCamera->lookAt(tn);
464  localCamera->setParentMode(PNODE_MOVEMENT);
465  localCamera->setClipRegion(1, 10000.0);
466  this->localPlayer->setParentMode(PNODE_ALL);
467  Vector* cameraOffset = new Vector (0, 5, -10);
468  TrackManager::getInstance()->condition(1, LEFTRIGHT, this->localPlayer);
469
470  this->sky->setParent(this->localCamera);
471
472  // initialize debug coord system
473  objectList = glGenLists(1);
474  glNewList (objectList, GL_COMPILE);
475
476  //TrackManager::getInstance()->drawGraph(.01);
477  //TrackManager::getInstance()->debug(2);
478  glEndList();
479
480  SoundEngine::getInstance()->setListener(this->localCamera);
481
482
483
484
485  ////////////
486  // STATIC //
487  ////////////
488
489  Gravity* test = new Gravity();
490
491  // SYSTEM TRAILING THE PLAYER
492  // Creating a Test Particle System
493
494  //new PhysicsConnection(system, gravity);
495  //    new PhysicsConnection(this->localPlayer, gravity);
496
497//   TestEntity* testEntity = new TestEntity();
498//   testEntity->setRelCoor(Vector(570, 10, -15));
499//   testEntity->setRelDir(Quaternion(M_PI, Vector(0, 1, 0)));
500//   this->spawn(testEntity);
501
502  TestEntity* testEntity2 = new TestEntity();
503  testEntity2->setAnim(RUN);
504  testEntity2->setRelCoor(Vector(2400, 25, 260));
505  testEntity2->setRelDir(Quaternion(M_PI, Vector(0, 1, 0)));
506  this->spawn(testEntity2);
507
508  TestEntity* testEntity3 = new TestEntity();
509  testEntity3->setAnim(RUN);
510  testEntity3->setRelCoor(Vector(2400, 25, 280));
511  testEntity3->setRelDir(Quaternion(M_PI, Vector(0, 1, 0)));
512  this->spawn(testEntity3);
513
514  TestEntity* testEntity4 = new TestEntity();
515  testEntity4->setAnim(RUN);
516  testEntity4->setRelCoor(Vector(2430, 25, 250));
517  testEntity4->setRelDir(Quaternion(M_PI, Vector(0, 1, 0)));
518  this->spawn(testEntity4);
519
520
521  PhysicsEngine::getInstance()->debug();
522
523  for(int i = 0; i < 100; i++)
524  {
525    WorldEntity* tmp = new NPC();
526    tmp->setAbsCoor(((float)rand()/RAND_MAX) * 2000, 40+ (float)rand()/RAND_MAX*30, ((float)rand()/RAND_MAX -.5) *500);
527    this->spawn(tmp);
528
529
530  }
531
532
533
534  ClassList::debug();
535
536  this->music = (OggPlayer*)ResourceManager::getInstance()->load("sound/00-luke_grey_-_hypermode.ogg", OGG, RP_LEVEL);
537  music->playback();
538}
539
540
541
542/**
543 *  loads the debug world: only for experimental stuff
544*/
545void World::loadDebugWorld(int worldID)
546{
547  /*monitor progress*/
548  this->glmis->step();
549  // stuff beyond this point remains to be loaded properly
550
551  // initializing the TrackManager
552  TrackManager::getInstance()->addPointV(Vector(150, -35, 5));
553  TrackManager::getInstance()->addPointV(Vector(200,-35, 5));
554  TrackManager::getInstance()->addPointV(Vector(250, -35, 5));
555  TrackManager::getInstance()->addPointV(Vector(320,-33,-.55));
556  TrackManager::getInstance()->setDuration(1);
557  TrackManager::getInstance()->setSavePoint();
558
559  TrackManager::getInstance()->addPointV(Vector(410, 0, 0));
560  TrackManager::getInstance()->addPointV(Vector(510, 20, -10));
561  TrackManager::getInstance()->addPointV(Vector(550, 20, -10));
562  TrackManager::getInstance()->addPointV(Vector(570, 20, -10));
563  TrackManager::getInstance()->setDuration(2);
564
565  TrackManager::getInstance()->forkS("testFork1,testFork2");
566  TrackManager::getInstance()->workOnS("testFork1");
567  TrackManager::getInstance()->addPointV(Vector(640, 25, -30));
568  TrackManager::getInstance()->addPointV(Vector(700, 40, -120));
569  TrackManager::getInstance()->addPointV(Vector(800, 50, -150));
570  TrackManager::getInstance()->addPointV(Vector(900, 60, -100));
571  TrackManager::getInstance()->addPointV(Vector(900, 60, -70));
572  TrackManager::getInstance()->addPointV(Vector(990, 65, -15));
573  TrackManager::getInstance()->addPointV(Vector(1050, 65, -10));
574  TrackManager::getInstance()->addPointV(Vector(1100, 65, -20));
575  TrackManager::getInstance()->setDuration(4);
576
577  TrackManager::getInstance()->workOnS("testFork2");
578  TrackManager::getInstance()->addPointV(Vector(640, 25, 20));
579  TrackManager::getInstance()->addPointV(Vector(670, 50, 120));
580  TrackManager::getInstance()->addPointV(Vector(700, 70, 80));
581  TrackManager::getInstance()->addPointV(Vector(800, 70, 65));
582  TrackManager::getInstance()->addPointV(Vector(850, 65, 65));
583  TrackManager::getInstance()->addPointV(Vector(920, 35, 40));
584  TrackManager::getInstance()->addPointV(Vector(945, 40, 40));
585  TrackManager::getInstance()->addPointV(Vector(970, 24, 40));
586  TrackManager::getInstance()->addPointV(Vector(1000, 40, -7));
587
588  TrackManager::getInstance()->setDuration(4);
589
590
591  TrackManager::getInstance()->joinS("testFork1,testFork2");
592
593  TrackManager::getInstance()->addPointV(Vector(1200, 60, -50));
594  TrackManager::getInstance()->addPointV(Vector(1300, 50, -50));
595  TrackManager::getInstance()->addPointV(Vector(1400, 40, -50));
596  TrackManager::getInstance()->addPointV(Vector(1500, 40, -60));
597  TrackManager::getInstance()->addPointV(Vector(1600, 35, -55));
598  TrackManager::getInstance()->addPointV(Vector(1700, 45, -40));
599  TrackManager::getInstance()->addPointV(Vector(1750, 60, -40));
600  TrackManager::getInstance()->addPointV(Vector(1770, 80, -40));
601  TrackManager::getInstance()->addPointV(Vector(1800, 100, -40));
602  TrackManager::getInstance()->setDuration(10);
603
604  TrackManager::getInstance()->finalize();
605
606
607  // LIGHT initialisation
608  LightManager::getInstance()->setAmbientColor(.1,.1,.1);
609//  LightManager::getInstance()->addLight();
610  LightManager::getInstance()->debug();
611
612  switch(this->debugWorldNr)
613    {
614      /*
615        this loads the hard-coded debug world. this only for simplicity and will be
616        removed by a reald world-loader, which interprets a world-file.
617        if you want to add an own debug world, just add a case DEBUG_WORLD_[nr] and
618        make whatever you want...
619      */
620    case DEBUG_WORLD_0:
621      {
622        LightManager::getInstance()->getLight()->setAbsCoor(-5.0, 10.0, -40.0);
623
624
625        this->localPlayer = new Player ();
626        this->localPlayer->setName ("player");
627        this->spawn (this->localPlayer);
628        this->localPlayer->setRelCoor(Vector(5,0,0));
629        /*monitor progress*/
630        this->glmis->step();
631
632
633        EventHandler::getInstance()->subscribe(this->localPlayer, ES_GAME, KeyMapper::PEV_FIRE1);
634        EventHandler::getInstance()->subscribe(this->localPlayer, ES_GAME, KeyMapper::PEV_NEXT_WEAPON);
635        EventHandler::getInstance()->subscribe(this->localPlayer, ES_GAME, KeyMapper::PEV_PREVIOUS_WEAPON);
636
637        /*
638        Field* testField = new Gravity();
639        testField->setMagnitude(10);
640        new PhysicsConnection(this->localPlayer, testField);
641        */
642
643        // bind camera
644        this->localCamera = new Camera();
645        this->localCamera->setName ("camera");
646        /*monitor progress*/
647        this->glmis->step();
648
649
650        // Create SkySphere
651        this->sky = new Skysphere("pictures/sky-replace.jpg");
652        this->sky->setName("SkySphere");
653        this->spawn(this->sky);
654        this->localCamera->addChild(this->sky);
655        this->sky->setParentMode(PNODE_MOVEMENT);
656        /*monitor progress*/
657        this->glmis->step();
658
659
660        terrain = new Terrain("worlds/newGround.obj");
661        terrain->setRelCoor(Vector(0,-10,0));
662        this->spawn(terrain);
663        /*monitor progress*/
664        this->glmis->step();
665
666        this->pilotNode = new PilotNode();
667        this->spawn(this->pilotNode);
668        this->pilotNode->setAbsCoor(Vector(150, -35, 5));
669        this->pilotNode->addChild(this->localPlayer);
670        this->pilotNode->addChild(this->localCamera);
671        this->localCamera->lookAt(this->localPlayer);
672
673        EventHandler::getInstance()->subscribe(this->pilotNode, ES_GAME, KeyMapper::PEV_UP);
674        EventHandler::getInstance()->subscribe(this->pilotNode, ES_GAME, KeyMapper::PEV_DOWN);
675        EventHandler::getInstance()->subscribe(this->pilotNode, ES_GAME, KeyMapper::PEV_LEFT);
676        EventHandler::getInstance()->subscribe(this->pilotNode, ES_GAME, KeyMapper::PEV_RIGHT);
677        EventHandler::getInstance()->subscribe(this->pilotNode, ES_GAME, EV_MOUSE_MOTION);
678
679        // bind input
680        Orxonox *orx = Orxonox::getInstance ();
681        //orx->getLocalInput()->bind (this->pilotNode);
682
683        /*
684        PNode* tn = TrackManager::getInstance()->getTrackNode();
685        tn->addChild(this->localPlayer);
686        this->localCamera->lookAt(tn);
687
688        tn->addChild(this->localCamera);
689        this->localPlayer->setParentMode(PNODE_ALL);
690        TrackManager::getInstance()->condition(2, LEFTRIGHT, this->localPlayer);
691        */
692        this->glmis->step();
693        break;
694      }
695    case DEBUG_WORLD_1:
696      {
697
698        break;
699      }
700    case DEBUG_WORLD_2:
701      {
702
703        break;
704      }
705    default:
706      break;
707    }
708}
709
710
711
712/**
713 *  initializes a new World shortly before start
714
715   this is the function, that will be loaded shortly before the world is
716   started
717*/
718ErrorMessage World::init()
719{
720  this->bPause = false;
721  this->pilotNode = NULL;
722}
723
724
725/**
726 *  starts the World
727*/
728ErrorMessage World::start()
729{
730  PRINTF(3)("World::start() - starting current World: nr %i\n", this->debugWorldNr);
731  this->bQuitOrxonox = false;
732  this->bQuitCurrentGame = false;
733  this->mainLoop();
734}
735
736/**
737 *  stops the world.
738
739   This happens, when the player decides to end the Level.
740*/
741ErrorMessage World::stop()
742{
743  PRINTF(3)("World::stop() - got stop signal\n");
744  this->bQuitCurrentGame = true;
745}
746
747/**
748 *  pauses the Game
749*/
750ErrorMessage World::pause()
751{
752  this->isPaused = true;
753}
754
755/**
756 *  ends the pause Phase
757*/
758ErrorMessage World::resume()
759{
760  this->isPaused = false;
761}
762
763/**
764 *  destroys the World
765*/
766ErrorMessage World::destroy()
767{
768
769}
770
771/**
772 *  shows the loading screen
773*/
774void World::displayLoadScreen ()
775{
776  PRINTF(3)("World::displayLoadScreen - start\n");
777
778  //GLMenuImageScreen*
779  this->glmis = new GLMenuImageScreen();
780  this->glmis->setMaximum(8);
781
782  PRINTF(3)("World::displayLoadScreen - end\n");
783}
784
785/**
786 *  removes the loadscreen, and changes over to the game
787
788   @todo take out the delay
789*/
790void World::releaseLoadScreen ()
791{
792  PRINTF(3)("World::releaseLoadScreen - start\n");
793  this->glmis->setValue(this->glmis->getMaximum());
794  PRINTF(3)("World::releaseLoadScreen - end\n");
795  delete this->glmis;
796}
797
798
799/**
800 *  gets the list of entities from the world
801 * @returns entity list
802*/
803tList<WorldEntity>* World::getEntities()
804{
805  return this->entities;
806}
807
808
809/**
810 *  this returns the current game time
811 * @returns elapsed game time
812*/
813double World::getGameTime()
814{
815  return this->gameTime;
816}
817
818
819/**
820 *  function to put your own debug stuff into it. it can display informations about
821   the current class/procedure
822*/
823void World::debug()
824{
825}
826
827
828/**
829  \brief main loop of the world: executing all world relevant function
830
831  in this loop we synchronize (if networked), handle input events, give the heart-beat to
832  all other member-entities of the world (tick to player, enemies etc.), checking for
833  collisions drawing everything to the screen.
834*/
835void World::mainLoop()
836{
837  this->lastFrame = SDL_GetTicks ();
838  PRINTF(3)("World::mainLoop() - Entering main loop\n");
839  while( !this->bQuitOrxonox && !this->bQuitCurrentGame) /* @todo implement pause */
840    {
841      ++this->cycle;
842      PRINTF(3)("World::mainloop() - number of entities: %i\n", this->entities->getSize());
843      // Network
844      this->synchronize ();
845      // Process input
846      this->handleInput ();
847      if( this->bQuitCurrentGame || this->bQuitOrxonox)
848          break;
849      // Process collision
850      this->collide ();
851      // Process time
852      this->tick ();
853      // Update the state
854      this->update ();
855      // Draw
856      this->display ();
857
858      //      for( int i = 0; i < 5000000; i++) {}
859      /* @todo this is to slow down the program for openGl Software emulator computers, reimplement*/
860    }
861  PRINTF(3)("World::mainLoop() - Exiting the main loop\n");
862}
863
864
865/**
866 *  synchronize local data with remote data
867*/
868void World::synchronize ()
869{
870  // Get remote input
871  // Update synchronizables
872}
873
874
875/**
876 *  run all input processing
877
878   the command node is the central input event dispatcher. the node uses the even-queue from
879   sdl and has its own event-passing-queue.
880*/
881void World::handleInput ()
882{
883  // localinput
884  //CommandNode* cn = Orxonox::getInstance()->getLocalInput();
885  //cn->process();
886
887  EventHandler::getInstance()->process();
888
889  // remoteinput
890}
891
892
893/**
894 *  advance the timeline
895
896   this calculates the time used to process one frame (with all input handling, drawing, etc)
897   the time is mesured in ms and passed to all world-entities and other classes that need
898   a heart-beat.
899*/
900void World::tick ()
901{
902  Uint32 currentFrame = SDL_GetTicks();
903  if(!this->bPause)
904    {
905      this->dt = currentFrame - this->lastFrame;
906
907      if( this->dt > 10)
908        {
909          float fps = 1000/dt;
910
911          // temporary, only for showing how fast the text-engine is
912          char tmpChar[20];
913          sprintf(tmpChar, "fps: %4.0f", fps);
914        }
915      else
916        {
917          /* the frame-rate is limited to 100 frames per second, all other things are for
918             nothing.
919          */
920          PRINTF(2)("fps = 1000 - frame rate is adjusted\n");
921          SDL_Delay(10-dt);
922          this->dt = 10;
923        }
924
925      this->dtS = (float)this->dt / 1000.0;
926      this->gameTime += this->dtS;
927
928      tIterator<WorldEntity>* iterator = this->entities->getIterator();
929      WorldEntity* entity = iterator->nextElement();
930      while( entity != NULL)
931        {
932          entity->tick (this->dtS);
933          entity = iterator->nextElement();
934        }
935      delete iterator;
936
937      /* update tick the rest */
938      TrackManager::getInstance()->tick(this->dtS);
939      this->localCamera->tick(this->dtS);
940      // tick the engines
941      AnimationPlayer::getInstance()->tick(this->dtS);
942      if (this->cycle > 5)
943        PhysicsEngine::getInstance()->tick(this->dtS);
944
945      ParticleEngine::getInstance()->tick(this->dtS);
946      GarbageCollector::getInstance()->tick(this->dtS);
947
948
949      /** actualy the Graphics Engine should tick the world not the other way around...
950         but since we like the things not too complicated we got it this way around
951         until there is need or time to do it the other way around.
952         @todo: GraphicsEngine ticks world: separation of processes and data...
953
954        bensch: in my opinion the GraphicsEngine could draw the world, but not tick it,
955         beceause graphics have nothing(or at least not much) to do with Motion.
956      */
957      GraphicsEngine::getInstance()->tick(this->dtS);
958    }
959  this->lastFrame = currentFrame;
960}
961
962
963/**
964 *  this function gives the world a consistant state
965
966   after ticking (updating the world state) this will give a constistant
967   state to the whole system.
968*/
969void World::update()
970{
971  GarbageCollector::getInstance()->update();
972  this->nullParent->update (this->dtS);
973
974  SoundEngine::getInstance()->update();
975  music->update();
976}
977
978
979void World::collide()
980{
981  CDEngine::getInstance()->checkCollisions();
982}
983
984/**
985 *  render the current frame
986
987   clear all buffers and draw the world
988*/
989void World::display ()
990{
991  // clear buffer
992  glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
993  // set camera
994  this->localCamera->apply ();
995  // draw world
996  this->draw();
997  // draw HUD
998  /** @todo draw HUD */
999  // flip buffers
1000  GraphicsEngine::swapBuffers();
1001  //SDL_Surface* screen = Orxonox::getInstance()->getScreen ();
1002  //SDL_Flip (screen);
1003}
1004
1005
1006/**
1007 *  runs through all entities calling their draw() methods
1008 */
1009void World::draw ()
1010{
1011  /* draw entities */
1012  WorldEntity* entity;
1013  glLoadIdentity();
1014  //entity = this->entities->enumerate();
1015  tIterator<WorldEntity>* iterator = this->entities->getIterator();
1016  entity = iterator->nextElement();
1017  while( entity != NULL )
1018  {
1019    if( entity->isVisible() ) entity->draw();
1020      //entity = this->entities->nextElement();
1021    entity = iterator->nextElement();
1022  }
1023  delete iterator;
1024
1025  glCallList (objectList);
1026
1027  ParticleEngine::getInstance()->draw();
1028
1029  GraphicsEngine::getInstance()->draw();
1030  //TextEngine::getInstance()->draw();
1031}
1032
1033/**
1034 *  add and spawn a new entity to this world
1035 * @param entity to be added
1036*/
1037void World::spawn(WorldEntity* entity)
1038{
1039  this->entities->add (entity);
1040  entity->postSpawn ();
1041}
1042
1043
1044/**
1045 *  add and spawn a new entity to this world
1046 * @param entity to be added
1047 * @param absCoor At what coordinates to add this entity.
1048 * @param absDir In which direction should it look.
1049*/
1050void World::spawn(WorldEntity* entity, Vector* absCoor, Quaternion* absDir)
1051{
1052  this->entities->add (entity);
1053
1054  entity->setAbsCoor (*absCoor);
1055  entity->setAbsDir (*absDir);
1056
1057  entity->postSpawn ();
1058}
1059
1060
1061/**
1062 *  add and spawn a new entity to this world
1063 * @param entity to be added
1064 * @param entity to be added to (PNode)
1065 * @param At what relative  coordinates to add this entity.
1066 * @param In which relative direction should it look.
1067*/
1068void World::spawn(WorldEntity* entity, PNode* parentNode,
1069                  Vector* relCoor, Quaternion* relDir)
1070{
1071  this->nullParent = NullParent::getInstance();
1072  if( parentNode != NULL)
1073    {
1074      parentNode->addChild (entity);
1075
1076      entity->setRelCoor (*relCoor);
1077      entity->setRelDir (*relDir);
1078
1079      this->entities->add (entity);
1080
1081      entity->postSpawn ();
1082    }
1083}
1084
1085
1086
1087/**
1088  \brief commands that the world must catch
1089  @returns false if not used by the world
1090*/
1091bool World::command(Command* cmd)
1092{
1093  if( !strcmp( cmd->cmd, CONFIG_NAME_VIEW0)) this->localCamera->setViewMode(VIEW_NORMAL);
1094  else if( !strcmp( cmd->cmd, CONFIG_NAME_VIEW1)) this->localCamera->setViewMode(VIEW_BEHIND);
1095  else if( !strcmp( cmd->cmd, CONFIG_NAME_VIEW2)) this->localCamera->setViewMode(VIEW_FRONT);
1096  else if( !strcmp( cmd->cmd, CONFIG_NAME_VIEW3)) this->localCamera->setViewMode(VIEW_LEFT);
1097  else if( !strcmp( cmd->cmd, CONFIG_NAME_VIEW4)) this->localCamera->setViewMode(VIEW_RIGHT);
1098  else if( !strcmp( cmd->cmd, CONFIG_NAME_VIEW5)) this->localCamera->setViewMode(VIEW_TOP);
1099  return false;
1100}
1101
1102void World::setPath( const char* name)
1103{
1104  if (this->path)
1105    delete this->path;
1106  if (ResourceManager::isFile(name))
1107  {
1108    this->path = new char[strlen(name)+1];
1109    strcpy(this->path, name);
1110  }
1111  else
1112    {
1113      this->path = new char[strlen(ResourceManager::getInstance()->getDataDir()) + strlen(name) +1];
1114      sprintf(this->path, "%s%s", ResourceManager::getInstance()->getDataDir(), name);
1115    }
1116}
1117
1118const char* World::getPath( void)
1119{
1120  return path;
1121}
Note: See TracBrowser for help on using the repository browser.