Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: particles: color is animatable too

File size: 29.9 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(.5);
477  system->setConserve(.8);
478  system->setRadius(0.0, 1.0, .6);
479  system->setRadius(.2, 3, .2);
480  system->setRadius(1.0, 0.0, .0);
481  system->setMass (0.0, 1.0);
482
483  system->setColor(0, .5,0,0,.5);
484  system->setColor(.5, 1,1,0,1);
485  system->setColor(1.0, 0,0,0,0);
486
487  // Creating a Test Particle Emitter
488  ParticleEmitter* emitter = new ParticleEmitter(Vector(-1, 0, 0), M_PI_4, 400, .5);
489  emitter->setType(EMITTER_DOT);
490  emitter->setSize(20);
491  emitter->setParent(this->localPlayer);
492  emitter->setRelCoor(Vector(-3,0,0));
493
494  Field* gravity = new Gravity();
495  gravity->setMagnitude(10.0);
496  //  gravity->setParent(this->localCamera->getTarget());
497 
498  // Add the Flow from the Emitter into the System
499  particleEngine->addConnection(emitter, system);
500
501  new PhysicsConnection(system, gravity);
502  //    new PhysicsConnection(this->localPlayer, gravity);
503 
504
505  TestEntity* testEntity = new TestEntity();
506  testEntity->setRelCoor(Vector(570, 10, -15));
507  //testEntity->setRelCoor(Vector(25, -10, -20));
508  testEntity->setRelDir(Quaternion(M_PI, Vector(0, 1, 0)));
509  this->spawn(testEntity);
510  //  this->localPlayer->addChild(testEntity);
511
512  new PhysicsConnection(testEntity, gravity);
513}
514
515
516
517/**
518   \brief loads the debug world: only for experimental stuff
519*/
520void World::loadDebugWorld(int worldID)
521{
522  /*monitor progress*/
523  this->glmis->step();
524  // stuff beyond this point remains to be loaded properly
525
526  // initializing the TrackManager
527  this->trackManager = TrackManager::getInstance();
528  //trackManager->addPoint(Vector(0,0,0));
529  trackManager->addPoint(Vector(150, -35, 5));
530  trackManager->addPoint(Vector(200,-35, 5));
531  trackManager->addPoint(Vector(250, -35, 5));
532  trackManager->addPoint(Vector(320,-33,-.55));
533  trackManager->setDuration(1);
534  trackManager->setSavePoint();
535
536  trackManager->addPoint(Vector(410, 0, 0));
537  trackManager->addPoint(Vector(510, 20, -10));
538  trackManager->addPoint(Vector(550, 20, -10));
539  trackManager->addPoint(Vector(570, 20, -10));
540  trackManager->setDuration(2);
541     
542  trackManager->forkS("testFork1,testFork2");
543  trackManager->workOn("testFork1");
544  trackManager->addPoint(Vector(640, 25, -30));
545  trackManager->addPoint(Vector(700, 40, -120));
546  trackManager->addPoint(Vector(800, 50, -150));
547  trackManager->addPoint(Vector(900, 60, -100));
548  trackManager->addPoint(Vector(900, 60, -70));
549  trackManager->addPoint(Vector(990, 65, -15));
550  trackManager->addPoint(Vector(1050, 65, -10));
551  trackManager->addPoint(Vector(1100, 65, -20));
552  trackManager->setDuration(4);
553
554  trackManager->workOn("testFork2");
555  trackManager->addPoint(Vector(640, 25, 20));
556  trackManager->addPoint(Vector(670, 50, 120));
557  trackManager->addPoint(Vector(700, 70, 80));
558  trackManager->addPoint(Vector(800, 70, 65));
559  trackManager->addPoint(Vector(850, 65, 65));
560  trackManager->addPoint(Vector(920, 35, 40));
561  trackManager->addPoint(Vector(945, 40, 40));
562  trackManager->addPoint(Vector(970, 24, 40));
563  trackManager->addPoint(Vector(1000, 40, -7));
564  trackManager->setDuration(4);
565     
566     
567  trackManager->joinS("testFork1,testFork2");
568       
569  trackManager->addPoint(Vector(1200, 60, -50));
570  trackManager->addPoint(Vector(1300, 50, -50));
571  trackManager->addPoint(Vector(1400, 40, -50));
572  trackManager->addPoint(Vector(1500, 40, -60));
573  trackManager->addPoint(Vector(1600, 35, -55));
574  trackManager->addPoint(Vector(1700, 45, -40));
575  trackManager->addPoint(Vector(1750, 60, -40));
576  trackManager->addPoint(Vector(1770, 80, -40));
577  trackManager->addPoint(Vector(1800, 100, -40));
578  trackManager->setDuration(10);
579 
580  trackManager->finalize();
581 
582
583  // LIGHT initialisation
584  lightMan->setAmbientColor(.1,.1,.1);
585  lightMan->addLight();
586  lightMan->debug();
587
588  switch(this->debugWorldNr)
589    {
590      /*
591        this loads the hard-coded debug world. this only for simplicity and will be
592        removed by a reald world-loader, which interprets a world-file.
593        if you want to add an own debug world, just add a case DEBUG_WORLD_[nr] and
594        make whatever you want...
595      */
596    case DEBUG_WORLD_0:
597      {
598        lightMan->setPosition(-5.0, 10.0, -40.0);
599
600
601        this->localPlayer = new Player ();
602        this->localPlayer->setName ("player");
603        this->spawn (this->localPlayer);
604        this->localPlayer->setRelCoor(Vector(5,0,0));
605        /*monitor progress*/
606        this->glmis->step();
607
608
609        this->eventHandler->subscribe(this->localPlayer, ES_GAME, KeyMapper::PEV_FIRE1);
610        this->eventHandler->subscribe(this->localPlayer, ES_GAME, KeyMapper::PEV_NEXT_WEAPON);
611        this->eventHandler->subscribe(this->localPlayer, ES_GAME, KeyMapper::PEV_PREVIOUS_WEAPON);
612
613        /*
614        Field* testField = new Gravity();
615        testField->setMagnitude(10);
616        new PhysicsConnection(this->localPlayer, testField);
617        */
618
619        // bind camera
620        this->localCamera = new Camera();
621        this->localCamera->setName ("camera");
622        /*monitor progress*/
623        this->glmis->step();
624
625
626        // Create SkySphere
627        this->sky = new Skysphere("pictures/sky-replace.jpg");
628        this->sky->setName("SkySphere");
629        this->spawn(this->sky);
630        this->localCamera->addChild(this->sky);
631        this->sky->setMode(PNODE_MOVEMENT);
632        /*monitor progress*/
633        this->glmis->step();
634
635
636        terrain = new Terrain("worlds/newGround.obj");
637        terrain->setRelCoor(Vector(0,-10,0));
638        this->spawn(terrain);
639        /*monitor progress*/
640        this->glmis->step();
641
642        this->pilotNode = new PilotNode();
643        this->spawn(this->pilotNode);
644        this->pilotNode->setAbsCoor(Vector(150, -35, 5));
645        this->pilotNode->addChild(this->localPlayer);
646        this->pilotNode->addChild(this->localCamera);
647        this->localCamera->lookAt(this->pilotNode);
648
649        this->eventHandler->subscribe(this->pilotNode, ES_GAME, KeyMapper::PEV_UP);
650        this->eventHandler->subscribe(this->pilotNode, ES_GAME, KeyMapper::PEV_DOWN);
651        this->eventHandler->subscribe(this->pilotNode, ES_GAME, KeyMapper::PEV_LEFT);
652        this->eventHandler->subscribe(this->pilotNode, ES_GAME, KeyMapper::PEV_RIGHT);
653        this->eventHandler->subscribe(this->pilotNode, ES_GAME, EV_MOUSE_MOTION);
654
655        // bind input
656        Orxonox *orx = Orxonox::getInstance ();
657        //orx->getLocalInput()->bind (this->pilotNode);     
658       
659        /*
660        PNode* tn = trackManager->getTrackNode();
661        tn->addChild(this->localPlayer);
662        this->localCamera->lookAt(tn);
663       
664        tn->addChild(this->localCamera);
665        this->localPlayer->setMode(PNODE_ALL);
666        trackManager->condition(2, LEFTRIGHT, this->localPlayer);
667        */
668        this->glmis->step();
669        break;
670      }
671    case DEBUG_WORLD_1:
672      {
673
674        break;
675      }
676    case DEBUG_WORLD_2:
677      {
678
679        break;
680      }
681    default:
682      break;
683    }
684}
685
686
687
688/**
689   \brief initializes a new World shortly before start
690
691   this is the function, that will be loaded shortly before the world is
692   started
693*/
694ErrorMessage World::init()
695{
696  this->bPause = false;
697  this->pilotNode = NULL;
698  CommandNode* cn = Orxonox::getInstance()->getLocalInput();
699  cn->addToWorld(this);
700  cn->enable(true);
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->setMode(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.