Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: prepeared to implement all system wide commands

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