Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: unsubscribtion from events, after object deatch

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