Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 4420 was 4420, checked in by patrick, 19 years ago

orxonox/trunk: faster and easier unsubscribe function implemented

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