Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: loading fields

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