Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: event_handler subscribe functionality improved

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  // remoteinput
969}
970
971
972/**
973   \brief advance the timeline
974
975   this calculates the time used to process one frame (with all input handling, drawing, etc)
976   the time is mesured in ms and passed to all world-entities and other classes that need
977   a heart-beat.
978*/
979void World::tick ()
980{
981  Uint32 currentFrame = SDL_GetTicks();
982  if(!this->bPause)
983    {
984      this->dt = currentFrame - this->lastFrame;
985     
986      if( this->dt > 0)
987        {
988          float fps = 1000/dt;
989
990          // temporary, only for showing how fast the text-engine is
991          char tmpChar[20];
992          sprintf(tmpChar, "fps: %4.0f", fps);
993        }
994      else
995        {
996          /* the frame-rate is limited to 100 frames per second, all other things are for
997             nothing.
998          */
999          PRINTF(2)("fps = 1000 - frame rate is adjusted\n");
1000          SDL_Delay(10);
1001          this->dt = 10;
1002        }
1003      //this->timeSlice (dt);
1004     
1005      /* function to let all entities tick (iterate through list) */
1006      this->dtS = (float)this->dt / 1000.0;     
1007      this->gameTime += this->dtS;
1008      //entity = entities->enumerate();
1009      tIterator<WorldEntity>* iterator = this->entities->getIterator();
1010      WorldEntity* entity = iterator->nextElement();
1011      while( entity != NULL) 
1012        { 
1013          entity->tick (this->dtS);
1014          entity = iterator->nextElement();
1015        }
1016      delete iterator;
1017
1018      /* update tick the rest */
1019      this->trackManager->tick(this->dt);
1020      this->localCamera->tick(this->dt);
1021      AnimationPlayer::getInstance()->tick(this->dtS);
1022      PhysicsEngine::getInstance()->tick(this->dtS);
1023
1024
1025      particleEngine->tick(this->dtS);
1026      this->garbageCollector->tick(this->dtS);
1027         
1028      /* actualy the Graphics Engine should tick the world not the other way around...
1029         but since we like the things not too complicated we got it this way around
1030         until there is need or time to do it the other way around.
1031         \todo: GraphicsEngine ticks world: separation of processes and data...
1032      */
1033      GraphicsEngine::getInstance()->tick(this->dtS);
1034    }
1035  this->lastFrame = currentFrame;
1036}
1037
1038
1039/**
1040   \brief this function gives the world a consistant state
1041
1042   after ticking (updating the world state) this will give a constistant
1043   state to the whole system.
1044*/
1045void World::update()
1046{
1047  this->garbageCollector->update();
1048  this->nullParent->update (this->dtS);
1049}
1050
1051
1052/**
1053   \brief render the current frame
1054   
1055   clear all buffers and draw the world
1056*/
1057void World::display ()
1058{
1059  // clear buffer
1060  glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
1061  // set camera
1062  this->localCamera->apply ();
1063  // draw world
1064  this->draw();
1065  // draw HUD
1066  /* \todo draw HUD */
1067  // flip buffers
1068  SDL_GL_SwapBuffers();
1069  //SDL_Surface* screen = Orxonox::getInstance()->getScreen ();
1070  //SDL_Flip (screen);
1071}
1072
1073
1074/**
1075   \brief add and spawn a new entity to this world
1076   \param entity to be added
1077*/
1078void World::spawn(WorldEntity* entity)
1079{
1080  this->entities->add (entity);
1081  entity->postSpawn ();
1082}
1083
1084
1085/**
1086   \brief add and spawn a new entity to this world
1087   \param entity to be added
1088   \param absCoor At what coordinates to add this entity.
1089   \param absDir In which direction should it look.
1090*/
1091void World::spawn(WorldEntity* entity, Vector* absCoor, Quaternion* absDir)
1092{
1093  this->entities->add (entity);
1094
1095  entity->setAbsCoor (*absCoor);
1096  entity->setAbsDir (*absDir);
1097
1098  entity->postSpawn ();
1099}
1100
1101
1102/**
1103   \brief add and spawn a new entity to this world
1104   \param entity to be added
1105   \param entity to be added to (PNode)
1106   \param At what relative  coordinates to add this entity.
1107   \param In which relative direction should it look.
1108*/
1109void World::spawn(WorldEntity* entity, PNode* parentNode, 
1110                  Vector* relCoor, Quaternion* relDir, 
1111                  int parentingMode)
1112{
1113  this->nullParent = NullParent::getInstance();
1114  if( parentNode != NULL)
1115    {
1116      parentNode->addChild (entity);
1117     
1118      entity->setRelCoor (*relCoor);
1119      entity->setRelDir (*relDir);
1120      entity->setMode(parentingMode);
1121     
1122      this->entities->add (entity);
1123     
1124      entity->postSpawn ();
1125    }
1126}
1127
1128
1129
1130/**
1131  \brief commands that the world must catch
1132  \returns false if not used by the world
1133*/
1134bool World::command(Command* cmd)
1135{
1136  if( !strcmp( cmd->cmd, CONFIG_NAME_VIEW0)) this->localCamera->setViewMode(VIEW_NORMAL);
1137  else if( !strcmp( cmd->cmd, CONFIG_NAME_VIEW1)) this->localCamera->setViewMode(VIEW_BEHIND);
1138  else if( !strcmp( cmd->cmd, CONFIG_NAME_VIEW2)) this->localCamera->setViewMode(VIEW_FRONT);
1139  else if( !strcmp( cmd->cmd, CONFIG_NAME_VIEW3)) this->localCamera->setViewMode(VIEW_LEFT);
1140  else if( !strcmp( cmd->cmd, CONFIG_NAME_VIEW4)) this->localCamera->setViewMode(VIEW_RIGHT);
1141  else if( !strcmp( cmd->cmd, CONFIG_NAME_VIEW5)) this->localCamera->setViewMode(VIEW_TOP);
1142  else if(this->pilotNode != NULL) if( !strcmp( cmd->cmd, "cursor")) this->pilotNode->command(cmd);
1143  return false;
1144}
1145
1146void World::setPath( const char* name)
1147{
1148  if (this->path)
1149    delete this->path;
1150  if (ResourceManager::isFile(name))
1151  {
1152    this->path = new char[strlen(name)+1];
1153    strcpy(this->path, name);
1154  }
1155  else
1156    {
1157      this->path = new char[strlen(ResourceManager::getInstance()->getDataDir()) + strlen(name) +1];
1158      sprintf(this->path, "%s%s", ResourceManager::getInstance()->getDataDir(), name);
1159    }
1160}
1161
1162const char* World::getPath( void)
1163{
1164  return path;
1165}
Note: See TracBrowser for help on using the repository browser.