Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: more loading (especially for physics)

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