Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: fixed major bug in PNode deletion cycle.
The Node did not unsubscribe itself at its parent

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