Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: setMode → setParentMode

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