Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: removed the debug draw again, rearangement in the mainloop: update/collision process order is very delcate

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(true);
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->setClipRegion(1, 10000.0);
380  this->localPlayer->setParentMode(PNODE_ALL);
381  Vector* cameraOffset = new Vector (0, 5, -10);
382  TrackManager::getInstance()->condition(1, LEFTRIGHT, this->localPlayer);
383
384  this->sky->setParent(this->localCamera);
385
386  // initialize debug coord system
387  objectList = glGenLists(1);
388  glNewList (objectList, GL_COMPILE);
389
390  //TrackManager::getInstance()->drawGraph(.01);
391  //TrackManager::getInstance()->debug(2);
392  glEndList();
393
394  SoundEngine::getInstance()->setListener(this->localCamera);
395
396
397
398  ////////////
399  // STATIC //
400  ////////////
401
402  Gravity* test = new Gravity();
403
404  // SYSTEM TRAILING THE PLAYER
405  // Creating a Test Particle System
406
407  //new PhysicsConnection(system, gravity);
408  //    new PhysicsConnection(this->localPlayer, gravity);
409
410//   TestEntity* testEntity = new TestEntity();
411//   testEntity->setRelCoor(Vector(570, 10, -15));
412//   testEntity->setRelDir(Quaternion(M_PI, Vector(0, 1, 0)));
413//   this->spawn(testEntity);
414
415  TestEntity* testEntity2 = new TestEntity();
416  testEntity2->setAnim(RUN);
417  testEntity2->setRelCoor(Vector(2400, 25, 260));
418  testEntity2->setRelDir(Quaternion(M_PI, Vector(0, 1, 0)));
419  this->spawn(testEntity2);
420
421  TestEntity* testEntity3 = new TestEntity();
422  testEntity3->setAnim(RUN);
423  testEntity3->setRelCoor(Vector(2400, 25, 280));
424  testEntity3->setRelDir(Quaternion(M_PI, Vector(0, 1, 0)));
425  this->spawn(testEntity3);
426
427  TestEntity* testEntity4 = new TestEntity();
428  testEntity4->setAnim(RUN);
429  testEntity4->setRelCoor(Vector(2430, 25, 250));
430  testEntity4->setRelDir(Quaternion(M_PI, Vector(0, 1, 0)));
431  this->spawn(testEntity4);
432
433
434  PhysicsEngine::getInstance()->debug();
435
436
437
438  for(int i = 0; i < 100; i++)
439  {
440    WorldEntity* tmp = new NPC();
441    tmp->setAbsCoor(((float)rand()/RAND_MAX) * 5000, 50/*+ (float)rand()/RAND_MAX*20*/, ((float)rand()/RAND_MAX -.5) *100);
442    this->spawn(tmp);
443
444
445  }
446
447
448
449  ClassList::debug();
450
451  this->music = (OggPlayer*)ResourceManager::getInstance()->load("sound/00-luke_grey_-_hypermode.ogg", OGG, RP_LEVEL);
452  music->playback();
453}
454
455
456
457/**
458 * creates a debug world: only for experimental stuff
459*/
460void World::loadDebugWorld(int worldID)
461{
462  /*monitor progress*/
463  this->glmis->step();
464  // stuff beyond this point remains to be loaded properly
465
466  // initializing the TrackManager
467  TrackManager::getInstance()->addPointV(Vector(150, -35, 5));
468  TrackManager::getInstance()->addPointV(Vector(200,-35, 5));
469  TrackManager::getInstance()->addPointV(Vector(250, -35, 5));
470  TrackManager::getInstance()->addPointV(Vector(320,-33,-.55));
471  TrackManager::getInstance()->setDuration(1);
472  TrackManager::getInstance()->setSavePoint();
473
474  TrackManager::getInstance()->addPointV(Vector(410, 0, 0));
475  TrackManager::getInstance()->addPointV(Vector(510, 20, -10));
476  TrackManager::getInstance()->addPointV(Vector(550, 20, -10));
477  TrackManager::getInstance()->addPointV(Vector(570, 20, -10));
478  TrackManager::getInstance()->setDuration(2);
479
480  TrackManager::getInstance()->forkS("testFork1,testFork2");
481  TrackManager::getInstance()->workOnS("testFork1");
482  TrackManager::getInstance()->addPointV(Vector(640, 25, -30));
483  TrackManager::getInstance()->addPointV(Vector(700, 40, -120));
484  TrackManager::getInstance()->addPointV(Vector(800, 50, -150));
485  TrackManager::getInstance()->addPointV(Vector(900, 60, -100));
486  TrackManager::getInstance()->addPointV(Vector(900, 60, -70));
487  TrackManager::getInstance()->addPointV(Vector(990, 65, -15));
488  TrackManager::getInstance()->addPointV(Vector(1050, 65, -10));
489  TrackManager::getInstance()->addPointV(Vector(1100, 65, -20));
490  TrackManager::getInstance()->setDuration(4);
491
492  TrackManager::getInstance()->workOnS("testFork2");
493  TrackManager::getInstance()->addPointV(Vector(640, 25, 20));
494  TrackManager::getInstance()->addPointV(Vector(670, 50, 120));
495  TrackManager::getInstance()->addPointV(Vector(700, 70, 80));
496  TrackManager::getInstance()->addPointV(Vector(800, 70, 65));
497  TrackManager::getInstance()->addPointV(Vector(850, 65, 65));
498  TrackManager::getInstance()->addPointV(Vector(920, 35, 40));
499  TrackManager::getInstance()->addPointV(Vector(945, 40, 40));
500  TrackManager::getInstance()->addPointV(Vector(970, 24, 40));
501  TrackManager::getInstance()->addPointV(Vector(1000, 40, -7));
502
503  TrackManager::getInstance()->setDuration(4);
504
505
506  TrackManager::getInstance()->joinS("testFork1,testFork2");
507
508  TrackManager::getInstance()->addPointV(Vector(1200, 60, -50));
509  TrackManager::getInstance()->addPointV(Vector(1300, 50, -50));
510  TrackManager::getInstance()->addPointV(Vector(1400, 40, -50));
511  TrackManager::getInstance()->addPointV(Vector(1500, 40, -60));
512  TrackManager::getInstance()->addPointV(Vector(1600, 35, -55));
513  TrackManager::getInstance()->addPointV(Vector(1700, 45, -40));
514  TrackManager::getInstance()->addPointV(Vector(1750, 60, -40));
515  TrackManager::getInstance()->addPointV(Vector(1770, 80, -40));
516  TrackManager::getInstance()->addPointV(Vector(1800, 100, -40));
517  TrackManager::getInstance()->setDuration(10);
518
519  TrackManager::getInstance()->finalize();
520
521
522  // LIGHT initialisation
523  LightManager::getInstance()->setAmbientColor(.1,.1,.1);
524//  LightManager::getInstance()->addLight();
525  LightManager::getInstance()->debug();
526
527  switch(this->debugWorldNr)
528    {
529      /*
530        this loads the hard-coded debug world. this only for simplicity and will be
531        removed by a reald world-loader, which interprets a world-file.
532        if you want to add an own debug world, just add a case DEBUG_WORLD_[nr] and
533        make whatever you want...
534      */
535    case DEBUG_WORLD_0:
536      {
537        LightManager::getInstance()->getLight()->setAbsCoor(-5.0, 10.0, -40.0);
538
539
540        this->localPlayer = new Player ();
541        this->localPlayer->setName ("player");
542        this->spawn (this->localPlayer);
543        this->localPlayer->setRelCoor(Vector(5,0,0));
544        /*monitor progress*/
545        this->glmis->step();
546
547
548        EventHandler::getInstance()->subscribe(this->localPlayer, ES_GAME, KeyMapper::PEV_FIRE1);
549        EventHandler::getInstance()->subscribe(this->localPlayer, ES_GAME, KeyMapper::PEV_NEXT_WEAPON);
550        EventHandler::getInstance()->subscribe(this->localPlayer, ES_GAME, KeyMapper::PEV_PREVIOUS_WEAPON);
551
552        /*
553        Field* testField = new Gravity();
554        testField->setMagnitude(10);
555        new PhysicsConnection(this->localPlayer, testField);
556        */
557
558        // bind camera
559        this->localCamera = new Camera();
560        this->localCamera->setName ("camera");
561        /*monitor progress*/
562        this->glmis->step();
563
564
565        // Create SkySphere
566        this->sky = new Skysphere("pictures/sky-replace.jpg");
567        this->sky->setName("SkySphere");
568        this->spawn(this->sky);
569        this->localCamera->addChild(this->sky);
570        this->sky->setParentMode(PNODE_MOVEMENT);
571        /*monitor progress*/
572        this->glmis->step();
573
574
575        terrain = new Terrain("worlds/newGround.obj");
576        terrain->setRelCoor(Vector(0,-10,0));
577        this->spawn(terrain);
578        /*monitor progress*/
579        this->glmis->step();
580
581        this->pilotNode = new PilotNode();
582        this->spawn(this->pilotNode);
583        this->pilotNode->setAbsCoor(Vector(150, -35, 5));
584        this->pilotNode->addChild(this->localPlayer);
585        this->pilotNode->addChild(this->localCamera);
586        this->localCamera->lookAt(this->localPlayer);
587
588        EventHandler::getInstance()->subscribe(this->pilotNode, ES_GAME, KeyMapper::PEV_UP);
589        EventHandler::getInstance()->subscribe(this->pilotNode, ES_GAME, KeyMapper::PEV_DOWN);
590        EventHandler::getInstance()->subscribe(this->pilotNode, ES_GAME, KeyMapper::PEV_LEFT);
591        EventHandler::getInstance()->subscribe(this->pilotNode, ES_GAME, KeyMapper::PEV_RIGHT);
592        EventHandler::getInstance()->subscribe(this->pilotNode, ES_GAME, EV_MOUSE_MOTION);
593
594        /*
595        PNode* tn = TrackManager::getInstance()->getTrackNode();
596        tn->addChild(this->localPlayer);
597        this->localCamera->lookAt(tn);
598
599        tn->addChild(this->localCamera);
600        this->localPlayer->setParentMode(PNODE_ALL);
601        TrackManager::getInstance()->condition(2, LEFTRIGHT, this->localPlayer);
602        */
603        this->glmis->step();
604        break;
605      }
606    case DEBUG_WORLD_1:
607      {
608
609        break;
610      }
611    case DEBUG_WORLD_2:
612      {
613
614        break;
615      }
616    default:
617      break;
618    }
619}
620
621/**
622 *  initializes a new World shortly before start
623 *
624 * this is the function, that will be loaded shortly before the world is
625 * started
626*/
627ErrorMessage World::init()
628{
629  this->bPause = false;
630  this->pilotNode = NULL;
631}
632
633
634/**
635 *  starts the World
636*/
637ErrorMessage World::start()
638{
639  PRINTF(3)("World::start() - starting current World: nr %i\n", this->debugWorldNr);
640  this->bQuitOrxonox = false;
641  this->bQuitCurrentGame = false;
642  this->mainLoop();
643}
644
645/**
646 *  stops the world.
647
648   This happens, when the player decides to end the Level.
649*/
650ErrorMessage World::stop()
651{
652  PRINTF(3)("World::stop() - got stop signal\n");
653  this->bQuitCurrentGame = true;
654}
655
656/**
657 *  pauses the Game
658*/
659ErrorMessage World::pause()
660{
661  this->isPaused = true;
662}
663
664/**
665 *  ends the pause Phase
666*/
667ErrorMessage World::resume()
668{
669  this->isPaused = false;
670}
671
672/**
673 *  destroys the World
674*/
675ErrorMessage World::destroy()
676{
677
678}
679
680/**
681 *  shows the loading screen
682*/
683void World::displayLoadScreen ()
684{
685  PRINTF(3)("World::displayLoadScreen - start\n");
686
687  //GLMenuImageScreen*
688  this->glmis = new GLMenuImageScreen();
689  this->glmis->setMaximum(8);
690
691  PRINTF(3)("World::displayLoadScreen - end\n");
692}
693
694/**
695 *  removes the loadscreen, and changes over to the game
696
697   @todo take out the delay
698*/
699void World::releaseLoadScreen ()
700{
701  PRINTF(3)("World::releaseLoadScreen - start\n");
702  this->glmis->setValue(this->glmis->getMaximum());
703  PRINTF(3)("World::releaseLoadScreen - end\n");
704  delete this->glmis;
705}
706
707
708/**
709 *  gets the list of entities from the world
710 * @returns entity list
711*/
712tList<WorldEntity>* World::getEntities()
713{
714  return this->entities;
715}
716
717
718/**
719 *  this returns the current game time
720 * @returns elapsed game time
721*/
722double World::getGameTime()
723{
724  return this->gameTime;
725}
726
727
728/**
729 *  function to put your own debug stuff into it. it can display informations about
730   the current class/procedure
731*/
732void World::debug()
733{
734}
735
736
737/**
738  \brief main loop of the world: executing all world relevant function
739
740  in this loop we synchronize (if networked), handle input events, give the heart-beat to
741  all other member-entities of the world (tick to player, enemies etc.), checking for
742  collisions drawing everything to the screen.
743*/
744void World::mainLoop()
745{
746  this->lastFrame = SDL_GetTicks ();
747  PRINTF(3)("World::mainLoop() - Entering main loop\n");
748  /* update the object position before game start - so there are no wrong coordinates used in the first processing */
749  NullParent::getInstance()->update (0.001f);
750
751  while( !this->bQuitOrxonox && !this->bQuitCurrentGame) /* @todo implement pause */
752    {
753      ++this->cycle;
754      PRINTF(3)("World::mainloop() - number of entities: %i\n", this->entities->getSize());
755      // Network
756      this->synchronize ();
757      // Process input
758      this->handleInput ();
759      if( this->bQuitCurrentGame || this->bQuitOrxonox)
760          break;
761      // Process time
762      this->tick ();
763      // Process collision
764      this->collide ();
765      // Update the state
766      this->update ();
767      // Draw
768      this->display ();
769    }
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  tIterator<WorldEntity>* iterator = this->entities->getIterator();
925  entity = iterator->nextElement();
926  while( entity != NULL )
927  {
928    if( entity->isVisible() ) entity->draw();
929    //entity->drawBVTree(2, 226);  // to draw the bounding boxes of the objects at level 2 for debug purp
930    entity = iterator->nextElement();
931  }
932  delete iterator;
933
934  glCallList (objectList);
935
936  ParticleEngine::getInstance()->draw();
937
938  GraphicsEngine::getInstance()->draw();
939  //TextEngine::getInstance()->draw();
940}
941
942/**
943 *  add and spawn a new entity to this world
944 * @param entity to be added
945*/
946void World::spawn(WorldEntity* entity)
947{
948  this->entities->add (entity);
949  entity->postSpawn ();
950}
951
952
953/**
954 *  add and spawn a new entity to this world
955 * @param entity to be added
956 * @param absCoor At what coordinates to add this entity.
957 * @param absDir In which direction should it look.
958*/
959void World::spawn(WorldEntity* entity, Vector* absCoor, Quaternion* absDir)
960{
961  this->entities->add (entity);
962
963  entity->setAbsCoor (*absCoor);
964  entity->setAbsDir (*absDir);
965
966  entity->postSpawn ();
967}
968
969
970/**
971 *  add and spawn a new entity to this world
972 * @param entity to be added
973 * @param entity to be added to (PNode)
974 * @param At what relative  coordinates to add this entity.
975 * @param In which relative direction should it look.
976*/
977void World::spawn(WorldEntity* entity, PNode* parentNode,
978                  Vector* relCoor, Quaternion* relDir)
979{
980  NullParent::getInstance();
981  if( parentNode != NULL)
982    {
983      parentNode->addChild (entity);
984
985      entity->setRelCoor (*relCoor);
986      entity->setRelDir (*relDir);
987
988      this->entities->add (entity);
989
990      entity->postSpawn ();
991    }
992}
993
994
995
996/**
997  \brief commands that the world must catch
998  @returns false if not used by the world
999*/
1000bool World::command(Command* cmd)
1001{
1002  if( !strcmp( cmd->cmd, CONFIG_NAME_VIEW0)) this->localCamera->setViewMode(VIEW_NORMAL);
1003  else if( !strcmp( cmd->cmd, CONFIG_NAME_VIEW1)) this->localCamera->setViewMode(VIEW_BEHIND);
1004  else if( !strcmp( cmd->cmd, CONFIG_NAME_VIEW2)) this->localCamera->setViewMode(VIEW_FRONT);
1005  else if( !strcmp( cmd->cmd, CONFIG_NAME_VIEW3)) this->localCamera->setViewMode(VIEW_LEFT);
1006  else if( !strcmp( cmd->cmd, CONFIG_NAME_VIEW4)) this->localCamera->setViewMode(VIEW_RIGHT);
1007  else if( !strcmp( cmd->cmd, CONFIG_NAME_VIEW5)) this->localCamera->setViewMode(VIEW_TOP);
1008  return false;
1009}
1010
1011void World::setPath( const char* name)
1012{
1013  if (this->path)
1014    delete this->path;
1015  if (ResourceManager::isFile(name))
1016  {
1017    this->path = new char[strlen(name)+1];
1018    strcpy(this->path, name);
1019  }
1020  else
1021    {
1022      this->path = new char[strlen(ResourceManager::getInstance()->getDataDir()) + strlen(name) +1];
1023      sprintf(this->path, "%s%s", ResourceManager::getInstance()->getDataDir(), name);
1024    }
1025}
1026
1027const char* World::getPath( void)
1028{
1029  return path;
1030}
Note: See TracBrowser for help on using the repository browser.