Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: minor cleanup of world.cc

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