Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: bugfixing the md2 animation class. there seems to be a problem with the animation itself which prevents the model from being drawn correctly

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