Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 4369 was 4349, checked in by bensch, 20 years ago

orxonox/trunk: ParticleEngine now has a draw-function, that makes sense

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