Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: now Objects should be affected by the PhysicsEngine too

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