Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: space craft can be controled via keys, nothing new yet

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