Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: fight against the mighty segfault

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