Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: small diffs

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