Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 4412 was 4412, checked in by patrick, 19 years ago

orxonox/trunk: now shooting and weapon change work again

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