Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: building the importer-stuff as a lib

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