Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: sparkling vulkano: you have to shoot, to make the effect visible

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