Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 4408 was 4407, checked in by patrick, 20 years ago

orxonox/trunk: event management now runs with new event-handler: no chance to kill current game without killall…

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