Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: vulcano get some smoke

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