Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: PhysicsEngine looks better (it speeds up things… but i do not exactly know if it works

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