Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: only obb boxes drawn, obbtree of projectiles also generated

File size: 28.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
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    char npcChar[10];
442    sprintf (npcChar, "NPC_%d", i);
443    tmp->setName(npcChar);
444    tmp->setAbsCoor(((float)rand()/RAND_MAX) * 5000, 50/*+ (float)rand()/RAND_MAX*20*/, ((float)rand()/RAND_MAX -.5) *100);
445    this->spawn(tmp);
446
447
448  }
449
450
451
452  ClassList::debug();
453
454  this->music = (OggPlayer*)ResourceManager::getInstance()->load("sound/00-luke_grey_-_hypermode.ogg", OGG, RP_LEVEL);
455  music->playback();
456}
457
458
459
460/**
461 * creates a debug world: only for experimental stuff
462*/
463void World::loadDebugWorld(int worldID)
464{
465  /*monitor progress*/
466  this->glmis->step();
467  // stuff beyond this point remains to be loaded properly
468
469  // initializing the TrackManager
470  TrackManager::getInstance()->addPointV(Vector(150, -35, 5));
471  TrackManager::getInstance()->addPointV(Vector(200,-35, 5));
472  TrackManager::getInstance()->addPointV(Vector(250, -35, 5));
473  TrackManager::getInstance()->addPointV(Vector(320,-33,-.55));
474  TrackManager::getInstance()->setDuration(1);
475  TrackManager::getInstance()->setSavePoint();
476
477  TrackManager::getInstance()->addPointV(Vector(410, 0, 0));
478  TrackManager::getInstance()->addPointV(Vector(510, 20, -10));
479  TrackManager::getInstance()->addPointV(Vector(550, 20, -10));
480  TrackManager::getInstance()->addPointV(Vector(570, 20, -10));
481  TrackManager::getInstance()->setDuration(2);
482
483  TrackManager::getInstance()->forkS("testFork1,testFork2");
484  TrackManager::getInstance()->workOnS("testFork1");
485  TrackManager::getInstance()->addPointV(Vector(640, 25, -30));
486  TrackManager::getInstance()->addPointV(Vector(700, 40, -120));
487  TrackManager::getInstance()->addPointV(Vector(800, 50, -150));
488  TrackManager::getInstance()->addPointV(Vector(900, 60, -100));
489  TrackManager::getInstance()->addPointV(Vector(900, 60, -70));
490  TrackManager::getInstance()->addPointV(Vector(990, 65, -15));
491  TrackManager::getInstance()->addPointV(Vector(1050, 65, -10));
492  TrackManager::getInstance()->addPointV(Vector(1100, 65, -20));
493  TrackManager::getInstance()->setDuration(4);
494
495  TrackManager::getInstance()->workOnS("testFork2");
496  TrackManager::getInstance()->addPointV(Vector(640, 25, 20));
497  TrackManager::getInstance()->addPointV(Vector(670, 50, 120));
498  TrackManager::getInstance()->addPointV(Vector(700, 70, 80));
499  TrackManager::getInstance()->addPointV(Vector(800, 70, 65));
500  TrackManager::getInstance()->addPointV(Vector(850, 65, 65));
501  TrackManager::getInstance()->addPointV(Vector(920, 35, 40));
502  TrackManager::getInstance()->addPointV(Vector(945, 40, 40));
503  TrackManager::getInstance()->addPointV(Vector(970, 24, 40));
504  TrackManager::getInstance()->addPointV(Vector(1000, 40, -7));
505
506  TrackManager::getInstance()->setDuration(4);
507
508
509  TrackManager::getInstance()->joinS("testFork1,testFork2");
510
511  TrackManager::getInstance()->addPointV(Vector(1200, 60, -50));
512  TrackManager::getInstance()->addPointV(Vector(1300, 50, -50));
513  TrackManager::getInstance()->addPointV(Vector(1400, 40, -50));
514  TrackManager::getInstance()->addPointV(Vector(1500, 40, -60));
515  TrackManager::getInstance()->addPointV(Vector(1600, 35, -55));
516  TrackManager::getInstance()->addPointV(Vector(1700, 45, -40));
517  TrackManager::getInstance()->addPointV(Vector(1750, 60, -40));
518  TrackManager::getInstance()->addPointV(Vector(1770, 80, -40));
519  TrackManager::getInstance()->addPointV(Vector(1800, 100, -40));
520  TrackManager::getInstance()->setDuration(10);
521
522  TrackManager::getInstance()->finalize();
523
524
525  // LIGHT initialisation
526  LightManager::getInstance()->setAmbientColor(.1,.1,.1);
527//  LightManager::getInstance()->addLight();
528  LightManager::getInstance()->debug();
529
530  switch(this->debugWorldNr)
531    {
532      /*
533        this loads the hard-coded debug world. this only for simplicity and will be
534        removed by a reald world-loader, which interprets a world-file.
535        if you want to add an own debug world, just add a case DEBUG_WORLD_[nr] and
536        make whatever you want...
537      */
538    case DEBUG_WORLD_0:
539      {
540        LightManager::getInstance()->getLight()->setAbsCoor(-5.0, 10.0, -40.0);
541
542
543        this->localPlayer = new Player ();
544        this->localPlayer->setName ("player");
545        this->spawn (this->localPlayer);
546        this->localPlayer->setRelCoor(Vector(5,0,0));
547        /*monitor progress*/
548        this->glmis->step();
549
550
551        EventHandler::getInstance()->subscribe(this->localPlayer, ES_GAME, KeyMapper::PEV_FIRE1);
552        EventHandler::getInstance()->subscribe(this->localPlayer, ES_GAME, KeyMapper::PEV_NEXT_WEAPON);
553        EventHandler::getInstance()->subscribe(this->localPlayer, ES_GAME, KeyMapper::PEV_PREVIOUS_WEAPON);
554
555        /*
556        Field* testField = new Gravity();
557        testField->setMagnitude(10);
558        new PhysicsConnection(this->localPlayer, testField);
559        */
560
561        // bind camera
562        this->localCamera = new Camera();
563        this->localCamera->setName ("camera");
564        /*monitor progress*/
565        this->glmis->step();
566
567
568        // Create SkySphere
569        this->sky = new Skysphere("pictures/sky-replace.jpg");
570        this->sky->setName("SkySphere");
571        this->spawn(this->sky);
572        this->localCamera->addChild(this->sky);
573        this->sky->setParentMode(PNODE_MOVEMENT);
574        /*monitor progress*/
575        this->glmis->step();
576
577
578        terrain = new Terrain("worlds/newGround.obj");
579        terrain->setRelCoor(Vector(0,-10,0));
580        this->spawn(terrain);
581        /*monitor progress*/
582        this->glmis->step();
583
584        this->pilotNode = new PilotNode();
585        this->spawn(this->pilotNode);
586        this->pilotNode->setAbsCoor(Vector(150, -35, 5));
587        this->pilotNode->addChild(this->localPlayer);
588        this->pilotNode->addChild(this->localCamera);
589        this->localCamera->lookAt(this->localPlayer);
590
591        EventHandler::getInstance()->subscribe(this->pilotNode, ES_GAME, KeyMapper::PEV_UP);
592        EventHandler::getInstance()->subscribe(this->pilotNode, ES_GAME, KeyMapper::PEV_DOWN);
593        EventHandler::getInstance()->subscribe(this->pilotNode, ES_GAME, KeyMapper::PEV_LEFT);
594        EventHandler::getInstance()->subscribe(this->pilotNode, ES_GAME, KeyMapper::PEV_RIGHT);
595        EventHandler::getInstance()->subscribe(this->pilotNode, ES_GAME, EV_MOUSE_MOTION);
596
597        /*
598        PNode* tn = TrackManager::getInstance()->getTrackNode();
599        tn->addChild(this->localPlayer);
600        this->localCamera->lookAt(tn);
601
602        tn->addChild(this->localCamera);
603        this->localPlayer->setParentMode(PNODE_ALL);
604        TrackManager::getInstance()->condition(2, LEFTRIGHT, this->localPlayer);
605        */
606        this->glmis->step();
607        break;
608      }
609    case DEBUG_WORLD_1:
610      {
611
612        break;
613      }
614    case DEBUG_WORLD_2:
615      {
616
617        break;
618      }
619    default:
620      break;
621    }
622}
623
624/**
625 *  initializes a new World shortly before start
626 *
627 * this is the function, that will be loaded shortly before the world is
628 * started
629*/
630ErrorMessage World::init()
631{
632  this->bPause = false;
633  this->pilotNode = NULL;
634
635  /* update the object position before game start - so there are no wrong coordinates used in the first processing */
636  NullParent::getInstance()->update (0.001f);
637  NullParent::getInstance()->update (0.001f);
638}
639
640
641/**
642 *  starts the World
643*/
644ErrorMessage World::start()
645{
646  PRINTF(3)("World::start() - starting current World: nr %i\n", this->debugWorldNr);
647  this->bQuitOrxonox = false;
648  this->bQuitCurrentGame = false;
649  this->mainLoop();
650}
651
652/**
653 *  stops the world.
654
655   This happens, when the player decides to end the Level.
656*/
657ErrorMessage World::stop()
658{
659  PRINTF(3)("World::stop() - got stop signal\n");
660  this->bQuitCurrentGame = true;
661}
662
663/**
664 *  pauses the Game
665*/
666ErrorMessage World::pause()
667{
668  this->isPaused = true;
669}
670
671/**
672 *  ends the pause Phase
673*/
674ErrorMessage World::resume()
675{
676  this->isPaused = false;
677}
678
679/**
680 *  destroys the World
681*/
682ErrorMessage World::destroy()
683{
684
685}
686
687/**
688 *  shows the loading screen
689*/
690void World::displayLoadScreen ()
691{
692  PRINTF(3)("World::displayLoadScreen - start\n");
693
694  //GLMenuImageScreen*
695  this->glmis = new GLMenuImageScreen();
696  this->glmis->setMaximum(8);
697
698  PRINTF(3)("World::displayLoadScreen - end\n");
699}
700
701/**
702 *  removes the loadscreen, and changes over to the game
703
704   @todo take out the delay
705*/
706void World::releaseLoadScreen ()
707{
708  PRINTF(3)("World::releaseLoadScreen - start\n");
709  this->glmis->setValue(this->glmis->getMaximum());
710  PRINTF(3)("World::releaseLoadScreen - end\n");
711  delete this->glmis;
712}
713
714
715/**
716 *  gets the list of entities from the world
717 * @returns entity list
718*/
719tList<WorldEntity>* World::getEntities()
720{
721  return this->entities;
722}
723
724
725/**
726 *  this returns the current game time
727 * @returns elapsed game time
728*/
729double World::getGameTime()
730{
731  return this->gameTime;
732}
733
734
735/**
736 *  function to put your own debug stuff into it. it can display informations about
737   the current class/procedure
738*/
739void World::debug()
740{
741}
742
743
744/**
745  \brief main loop of the world: executing all world relevant function
746
747  in this loop we synchronize (if networked), handle input events, give the heart-beat to
748  all other member-entities of the world (tick to player, enemies etc.), checking for
749  collisions drawing everything to the screen.
750*/
751void World::mainLoop()
752{
753  this->lastFrame = SDL_GetTicks ();
754  PRINTF(3)("World::mainLoop() - Entering main loop\n");
755
756  while( !this->bQuitOrxonox && !this->bQuitCurrentGame) /* @todo implement pause */
757    {
758      ++this->cycle;
759      PRINTF(4)("World::mainloop() - number of entities: %i\n", this->entities->getSize());
760      // Network
761      this->synchronize ();
762      // Process input
763      this->handleInput ();
764      if( this->bQuitCurrentGame || this->bQuitOrxonox)
765          break;
766      // Process time
767      this->tick ();
768      // Process collision
769      this->collide ();
770      // Update the state
771      this->update ();
772      // Draw
773      this->display ();
774    }
775
776  PRINTF(3)("World::mainLoop() - Exiting the main loop\n");
777}
778
779
780/**
781 *  synchronize local data with remote data
782*/
783void World::synchronize ()
784{
785  // Get remote input
786  // Update synchronizables
787}
788
789
790/**
791 *  run all input processing
792
793   the command node is the central input event dispatcher. the node uses the even-queue from
794   sdl and has its own event-passing-queue.
795*/
796void World::handleInput ()
797{
798  // localinput
799  //CommandNode* cn = Orxonox::getInstance()->getLocalInput();
800  //cn->process();
801
802  EventHandler::getInstance()->process();
803
804  // remoteinput
805}
806
807
808/**
809 *  advance the timeline
810
811   this calculates the time used to process one frame (with all input handling, drawing, etc)
812   the time is mesured in ms and passed to all world-entities and other classes that need
813   a heart-beat.
814*/
815void World::tick ()
816{
817  Uint32 currentFrame = SDL_GetTicks();
818  if(!this->bPause)
819    {
820      this->dt = currentFrame - this->lastFrame;
821
822      if( this->dt > 10)
823        {
824          float fps = 1000/dt;
825
826          // temporary, only for showing how fast the text-engine is
827          char tmpChar[20];
828          sprintf(tmpChar, "fps: %4.0f", fps);
829        }
830      else
831        {
832          /* the frame-rate is limited to 100 frames per second, all other things are for
833             nothing.
834          */
835          PRINTF(3)("fps = 1000 - frame rate is adjusted\n");
836          SDL_Delay(10-dt);
837          this->dt = 10;
838        }
839
840      this->dtS = (float)this->dt / 1000.0;
841      this->gameTime += this->dtS;
842
843      tIterator<WorldEntity>* iterator = this->entities->getIterator();
844      WorldEntity* entity = iterator->nextElement();
845      while( entity != NULL)
846        {
847          entity->tick (this->dtS);
848          entity = iterator->nextElement();
849        }
850      delete iterator;
851
852      /* update tick the rest */
853      TrackManager::getInstance()->tick(this->dtS);
854      this->localCamera->tick(this->dtS);
855      // tick the engines
856      AnimationPlayer::getInstance()->tick(this->dtS);
857//      if (this->cycle > 5)
858        PhysicsEngine::getInstance()->tick(this->dtS);
859
860      ParticleEngine::getInstance()->tick(this->dtS);
861      GarbageCollector::getInstance()->tick(this->dtS);
862
863
864      /** actualy the Graphics Engine should tick the world not the other way around...
865         but since we like the things not too complicated we got it this way around
866         until there is need or time to do it the other way around.
867         @todo: GraphicsEngine ticks world: separation of processes and data...
868
869        bensch: in my opinion the GraphicsEngine could draw the world, but not tick it,
870         beceause graphics have nothing(or at least not much) to do with Motion.
871      */
872      GraphicsEngine::getInstance()->tick(this->dtS);
873    }
874  this->lastFrame = currentFrame;
875}
876
877
878/**
879 *  this function gives the world a consistant state
880
881   after ticking (updating the world state) this will give a constistant
882   state to the whole system.
883*/
884void World::update()
885{
886  GarbageCollector::getInstance()->update();
887  NullParent::getInstance()->update (this->dtS);
888
889  SoundEngine::getInstance()->update();
890  //music->update();
891}
892
893
894void World::collide()
895{
896  CDEngine::getInstance()->checkCollisions();
897}
898
899/**
900 *  render the current frame
901
902   clear all buffers and draw the world
903*/
904void World::display ()
905{
906  // clear buffer
907  glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
908  // set camera
909  this->localCamera->apply ();
910  // draw world
911  this->draw();
912  // draw HUD
913  /** @todo draw HUD */
914  // flip buffers
915  GraphicsEngine::swapBuffers();
916  //SDL_Surface* screen = Orxonox::getInstance()->getScreen ();
917  //SDL_Flip (screen);
918}
919
920
921/**
922 *  runs through all entities calling their draw() methods
923 */
924void World::draw ()
925{
926  /* draw entities */
927  WorldEntity* entity;
928  glLoadIdentity();
929  tIterator<WorldEntity>* iterator = this->entities->getIterator();
930  entity = iterator->nextElement();
931  while( entity != NULL )
932  {
933    //if( entity->isVisible() ) entity->draw();
934    entity->drawBVTree(2, 226);  // to draw the bounding boxes of the objects at level 2 for debug purp
935    entity = iterator->nextElement();
936  }
937  delete iterator;
938
939  glCallList (objectList);
940
941  ParticleEngine::getInstance()->draw();
942
943  GraphicsEngine::getInstance()->draw();
944  //TextEngine::getInstance()->draw();
945}
946
947/**
948 *  add and spawn a new entity to this world
949 * @param entity to be added
950*/
951void World::spawn(WorldEntity* entity)
952{
953  this->entities->add (entity);
954  entity->postSpawn ();
955}
956
957
958/**
959 *  add and spawn a new entity to this world
960 * @param entity to be added
961 * @param absCoor At what coordinates to add this entity.
962 * @param absDir In which direction should it look.
963*/
964void World::spawn(WorldEntity* entity, Vector* absCoor, Quaternion* absDir)
965{
966  this->entities->add (entity);
967
968  entity->setAbsCoor (*absCoor);
969  entity->setAbsDir (*absDir);
970
971  entity->postSpawn ();
972}
973
974
975/**
976 *  add and spawn a new entity to this world
977 * @param entity to be added
978 * @param entity to be added to (PNode)
979 * @param At what relative  coordinates to add this entity.
980 * @param In which relative direction should it look.
981*/
982void World::spawn(WorldEntity* entity, PNode* parentNode,
983                  Vector* relCoor, Quaternion* relDir)
984{
985  NullParent::getInstance();
986  if( parentNode != NULL)
987    {
988      parentNode->addChild (entity);
989
990      entity->setRelCoor (*relCoor);
991      entity->setRelDir (*relDir);
992
993      this->entities->add (entity);
994
995      entity->postSpawn ();
996    }
997}
998
999
1000
1001/**
1002  \brief commands that the world must catch
1003  @returns false if not used by the world
1004*/
1005bool World::command(Command* cmd)
1006{
1007  if( !strcmp( cmd->cmd, CONFIG_NAME_VIEW0)) this->localCamera->setViewMode(VIEW_NORMAL);
1008  else if( !strcmp( cmd->cmd, CONFIG_NAME_VIEW1)) this->localCamera->setViewMode(VIEW_BEHIND);
1009  else if( !strcmp( cmd->cmd, CONFIG_NAME_VIEW2)) this->localCamera->setViewMode(VIEW_FRONT);
1010  else if( !strcmp( cmd->cmd, CONFIG_NAME_VIEW3)) this->localCamera->setViewMode(VIEW_LEFT);
1011  else if( !strcmp( cmd->cmd, CONFIG_NAME_VIEW4)) this->localCamera->setViewMode(VIEW_RIGHT);
1012  else if( !strcmp( cmd->cmd, CONFIG_NAME_VIEW5)) this->localCamera->setViewMode(VIEW_TOP);
1013  return false;
1014}
1015
1016void World::setPath( const char* name)
1017{
1018  if (this->path)
1019    delete this->path;
1020  if (ResourceManager::isFile(name))
1021  {
1022    this->path = new char[strlen(name)+1];
1023    strcpy(this->path, name);
1024  }
1025  else
1026    {
1027      this->path = new char[strlen(ResourceManager::getInstance()->getDataDir()) + strlen(name) +1];
1028      sprintf(this->path, "%s%s", ResourceManager::getInstance()->getDataDir(), name);
1029    }
1030}
1031
1032const char* World::getPath( void)
1033{
1034  return path;
1035}
Note: See TracBrowser for help on using the repository browser.