Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: cd now works all obj-obj collisions are detected and for each is a message displayed in the console. since the small enemy spacefracts follow the player at one point - there are many collisions at the same time…

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  while( !this->bQuitOrxonox && !this->bQuitCurrentGame) /* @todo implement pause */
749    {
750      ++this->cycle;
751      PRINTF(3)("World::mainloop() - number of entities: %i\n", this->entities->getSize());
752      // Network
753      this->synchronize ();
754      // Process input
755      this->handleInput ();
756      if( this->bQuitCurrentGame || this->bQuitOrxonox)
757          break;
758      // Process time
759      this->tick ();
760      // Update the state
761      this->update ();
762      // Process collision
763      this->collide ();
764      // Draw
765      this->display ();
766
767      //      for( int i = 0; i < 5000000; i++) {}
768      /* @todo this is to slow down the program for openGl Software emulator computers, reimplement*/
769    }
770  PRINTF(3)("World::mainLoop() - Exiting the main loop\n");
771}
772
773
774/**
775 *  synchronize local data with remote data
776*/
777void World::synchronize ()
778{
779  // Get remote input
780  // Update synchronizables
781}
782
783
784/**
785 *  run all input processing
786
787   the command node is the central input event dispatcher. the node uses the even-queue from
788   sdl and has its own event-passing-queue.
789*/
790void World::handleInput ()
791{
792  // localinput
793  //CommandNode* cn = Orxonox::getInstance()->getLocalInput();
794  //cn->process();
795
796  EventHandler::getInstance()->process();
797
798  // remoteinput
799}
800
801
802/**
803 *  advance the timeline
804
805   this calculates the time used to process one frame (with all input handling, drawing, etc)
806   the time is mesured in ms and passed to all world-entities and other classes that need
807   a heart-beat.
808*/
809void World::tick ()
810{
811  Uint32 currentFrame = SDL_GetTicks();
812  if(!this->bPause)
813    {
814      this->dt = currentFrame - this->lastFrame;
815
816      if( this->dt > 10)
817        {
818          float fps = 1000/dt;
819
820          // temporary, only for showing how fast the text-engine is
821          char tmpChar[20];
822          sprintf(tmpChar, "fps: %4.0f", fps);
823        }
824      else
825        {
826          /* the frame-rate is limited to 100 frames per second, all other things are for
827             nothing.
828          */
829          PRINTF(2)("fps = 1000 - frame rate is adjusted\n");
830          SDL_Delay(10-dt);
831          this->dt = 10;
832        }
833
834      this->dtS = (float)this->dt / 1000.0;
835      this->gameTime += this->dtS;
836
837      tIterator<WorldEntity>* iterator = this->entities->getIterator();
838      WorldEntity* entity = iterator->nextElement();
839      while( entity != NULL)
840        {
841          entity->tick (this->dtS);
842          entity = iterator->nextElement();
843        }
844      delete iterator;
845
846      /* update tick the rest */
847      TrackManager::getInstance()->tick(this->dtS);
848      this->localCamera->tick(this->dtS);
849      // tick the engines
850      AnimationPlayer::getInstance()->tick(this->dtS);
851//      if (this->cycle > 5)
852        PhysicsEngine::getInstance()->tick(this->dtS);
853
854      ParticleEngine::getInstance()->tick(this->dtS);
855      GarbageCollector::getInstance()->tick(this->dtS);
856
857
858      /** actualy the Graphics Engine should tick the world not the other way around...
859         but since we like the things not too complicated we got it this way around
860         until there is need or time to do it the other way around.
861         @todo: GraphicsEngine ticks world: separation of processes and data...
862
863        bensch: in my opinion the GraphicsEngine could draw the world, but not tick it,
864         beceause graphics have nothing(or at least not much) to do with Motion.
865      */
866      GraphicsEngine::getInstance()->tick(this->dtS);
867    }
868  this->lastFrame = currentFrame;
869}
870
871
872/**
873 *  this function gives the world a consistant state
874
875   after ticking (updating the world state) this will give a constistant
876   state to the whole system.
877*/
878void World::update()
879{
880  GarbageCollector::getInstance()->update();
881  NullParent::getInstance()->update (this->dtS);
882
883  SoundEngine::getInstance()->update();
884  //music->update();
885}
886
887
888void World::collide()
889{
890  CDEngine::getInstance()->checkCollisions();
891}
892
893/**
894 *  render the current frame
895
896   clear all buffers and draw the world
897*/
898void World::display ()
899{
900  // clear buffer
901  glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
902  // set camera
903  this->localCamera->apply ();
904  // draw world
905  this->draw();
906  // draw HUD
907  /** @todo draw HUD */
908  // flip buffers
909  GraphicsEngine::swapBuffers();
910  //SDL_Surface* screen = Orxonox::getInstance()->getScreen ();
911  //SDL_Flip (screen);
912}
913
914
915/**
916 *  runs through all entities calling their draw() methods
917 */
918void World::draw ()
919{
920  /* draw entities */
921  WorldEntity* entity;
922  glLoadIdentity();
923  tIterator<WorldEntity>* iterator = this->entities->getIterator();
924  entity = iterator->nextElement();
925  while( entity != NULL )
926  {
927    if( entity->isVisible() ) entity->draw();
928    entity->drawBVTree(2, 226);
929    entity = iterator->nextElement();
930  }
931  delete iterator;
932
933  glCallList (objectList);
934
935  ParticleEngine::getInstance()->draw();
936
937  GraphicsEngine::getInstance()->draw();
938  //TextEngine::getInstance()->draw();
939}
940
941/**
942 *  add and spawn a new entity to this world
943 * @param entity to be added
944*/
945void World::spawn(WorldEntity* entity)
946{
947  this->entities->add (entity);
948  entity->postSpawn ();
949}
950
951
952/**
953 *  add and spawn a new entity to this world
954 * @param entity to be added
955 * @param absCoor At what coordinates to add this entity.
956 * @param absDir In which direction should it look.
957*/
958void World::spawn(WorldEntity* entity, Vector* absCoor, Quaternion* absDir)
959{
960  this->entities->add (entity);
961
962  entity->setAbsCoor (*absCoor);
963  entity->setAbsDir (*absDir);
964
965  entity->postSpawn ();
966}
967
968
969/**
970 *  add and spawn a new entity to this world
971 * @param entity to be added
972 * @param entity to be added to (PNode)
973 * @param At what relative  coordinates to add this entity.
974 * @param In which relative direction should it look.
975*/
976void World::spawn(WorldEntity* entity, PNode* parentNode,
977                  Vector* relCoor, Quaternion* relDir)
978{
979  NullParent::getInstance();
980  if( parentNode != NULL)
981    {
982      parentNode->addChild (entity);
983
984      entity->setRelCoor (*relCoor);
985      entity->setRelDir (*relDir);
986
987      this->entities->add (entity);
988
989      entity->postSpawn ();
990    }
991}
992
993
994
995/**
996  \brief commands that the world must catch
997  @returns false if not used by the world
998*/
999bool World::command(Command* cmd)
1000{
1001  if( !strcmp( cmd->cmd, CONFIG_NAME_VIEW0)) this->localCamera->setViewMode(VIEW_NORMAL);
1002  else if( !strcmp( cmd->cmd, CONFIG_NAME_VIEW1)) this->localCamera->setViewMode(VIEW_BEHIND);
1003  else if( !strcmp( cmd->cmd, CONFIG_NAME_VIEW2)) this->localCamera->setViewMode(VIEW_FRONT);
1004  else if( !strcmp( cmd->cmd, CONFIG_NAME_VIEW3)) this->localCamera->setViewMode(VIEW_LEFT);
1005  else if( !strcmp( cmd->cmd, CONFIG_NAME_VIEW4)) this->localCamera->setViewMode(VIEW_RIGHT);
1006  else if( !strcmp( cmd->cmd, CONFIG_NAME_VIEW5)) this->localCamera->setViewMode(VIEW_TOP);
1007  return false;
1008}
1009
1010void World::setPath( const char* name)
1011{
1012  if (this->path)
1013    delete this->path;
1014  if (ResourceManager::isFile(name))
1015  {
1016    this->path = new char[strlen(name)+1];
1017    strcpy(this->path, name);
1018  }
1019  else
1020    {
1021      this->path = new char[strlen(ResourceManager::getInstance()->getDataDir()) + strlen(name) +1];
1022      sprintf(this->path, "%s%s", ResourceManager::getInstance()->getDataDir(), name);
1023    }
1024}
1025
1026const char* World::getPath( void)
1027{
1028  return path;
1029}
Note: See TracBrowser for help on using the repository browser.