Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: track: doxy-tags, redesign, and minor speed-update

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