Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: further work on debug level

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