Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: loading fields

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