Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: working on an alternativ flight mode and a new event handlig system at the same time. crazy…

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