Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/network/src/story_entities/game_world.cc @ 6389

Last change on this file since 6389 was 6387, checked in by patrick, 18 years ago

network: much more work on the StoryEntity functions and reimplementations of the DataTanks of each StoryEntity

File size: 18.1 KB
Line 
1/*
2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 orx
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10
11   ### File Specific:
12   main-programmer: Patrick Boenzli
13   co-programmer: Christian Meyer
14   co-programmer: Benjamin Grauer
15*/
16
17#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_WORLD
18
19#include "game_world.h"
20
21#include "shell_command.h"
22#include "resource_manager.h"
23#include "state.h"
24
25#include "p_node.h"
26#include "world_entity.h"
27#include "player.h"
28#include "camera.h"
29#include "environment.h"
30#include "terrain.h"
31
32#include "test_entity.h"
33#include "terrain.h"
34#include "light.h"
35#include "load_param.h"
36#include "shell.h"
37
38#include "fast_factory.h"
39#include "animation_player.h"
40#include "particle_engine.h"
41#include "graphics_engine.h"
42#include "physics_engine.h"
43#include "fields.h"
44
45#include "md2Model.h"
46
47#include "glmenu_imagescreen.h"
48#include "game_loader.h"
49
50#include "animation3d.h"
51
52#include "substring.h"
53
54#include "factory.h"
55
56#include "weapons/projectile.h"
57#include "event_handler.h"
58#include "sound_engine.h"
59#include "ogg_player.h"
60
61#include "class_list.h"
62
63#include "cd_engine.h"
64#include "npcs/npc_test1.h"
65#include "shader.h"
66
67#include "playable.h"
68#include "network_manager.h"
69#include "playable.h"
70
71
72SHELL_COMMAND(speed, GameWorld, setSpeed);
73SHELL_COMMAND(togglePNodeVisibility, GameWorld, togglePNodeVisibility);
74SHELL_COMMAND(toggleBVVisibility, GameWorld, toggleBVVisibility);
75
76using namespace std;
77
78//! This creates a Factory to fabricate a GameWorld
79//CREATE_FACTORY(GameWorld, CL_GAME_WORLD);
80
81
82
83GameWorld::GameWorld(const TiXmlElement* root)
84  : StoryEntity()
85{
86  this->setClassID(CL_GAME_WORLD, "GameWorld");
87  this->setName("Preloaded World - no name yet");
88
89  this->gameTime = 0.0f;
90  this->setSpeed(1.0f);
91  this->music = NULL;
92  this->shell = NULL;
93
94  this->showPNodes = false;
95  this->showBV = false;
96
97  this->path = NULL;
98
99  this->gameWorldData = new GameWorldData();
100}
101
102/**
103 *  remove the GameWorld from memory
104 *
105 *  delete everything explicitly, that isn't contained in the parenting tree!
106 *  things contained in the tree are deleted automaticaly
107 */
108GameWorld::~GameWorld ()
109{
110  if( this->gameWorldData)
111    delete this->gameWorldData;
112}
113
114
115
116/**
117 * loads the parameters of a GameWorld from an XML-element
118 * @param root the XML-element to load from
119 */
120void GameWorld::loadParams(const TiXmlElement* root)
121{
122  static_cast<StoryEntity*>(this)->loadParams(root);
123
124  LoadParam(root, "path", this, GameWorld, setPath)
125    .describe("The Filename of this GameWorld (relative from the data-dir)");
126
127  PRINTF(4)("Loaded GameWorld specific stuff\n");
128}
129
130
131/**
132 * this is executed just before load
133 *
134 * since the load function sometimes needs data, that has been initialized
135 * before the load and after the proceeding storyentity has finished
136*/
137ErrorMessage GameWorld::init()
138{
139  State::setObjectManager(&this->objectManager);
140  this->cycle = 0;
141
142  /* init the world interface */
143  this->shell = new Shell();
144
145  LightManager::getInstance();
146  PNode::getNullParent();
147
148  AnimationPlayer::getInstance(); // initializes the animationPlayer
149  ParticleEngine::getInstance();
150  PhysicsEngine::getInstance();
151
152  this->gameWorldData->localCamera = new Camera();
153  this->gameWorldData->localCamera->setName ("GameWorld-Camera");
154
155  State::setCamera(this->gameWorldData->localCamera, this->gameWorldData->localCamera->getTarget());
156
157  GraphicsEngine::getInstance()->displayFPS(true);
158}
159
160
161/**
162 *  loads the GameWorld by initializing all resources, and set their default values.
163 */
164ErrorMessage GameWorld::loadData()
165{
166  this->displayLoadScreen();
167
168  PRINTF(3)("> Loading world: '%s'\n", getPath());
169  TiXmlElement* element;
170  GameLoader* loader = GameLoader::getInstance();
171
172  if( getPath() == NULL)
173    {
174      PRINTF(1)("GameWorld has no path specified for loading");
175      return (ErrorMessage){213,"Path not specified","GameWorld::load()"};
176    }
177
178  TiXmlDocument* XMLDoc = new TiXmlDocument( getPath());
179  // load the campaign document
180  if( !XMLDoc->LoadFile())
181  {
182    // report an error
183    PRINTF(1)("loading XML File: %s @ %s:l%d:c%d\n", XMLDoc->ErrorDesc(), this->getPath(), XMLDoc->ErrorRow(), XMLDoc->ErrorCol());
184    delete XMLDoc;
185    return (ErrorMessage){213,"XML File parsing error","GameWorld::load()"};
186  }
187
188  // check basic validity
189  TiXmlElement* root = XMLDoc->RootElement();
190  assert( root != NULL);
191
192  if( root == NULL || root->Value() == NULL || strcmp( root->Value(), "WorldDataFile"))
193    {
194      // report an error
195      PRINTF(1)("Specified XML File is not an orxonox world data file (WorldDataFile element missing)\n");
196      delete XMLDoc;
197      return (ErrorMessage){213,"Path not a WorldDataFile","GameWorld::load()"};
198    }
199
200  // load the parameters
201  // name
202  const char* string = grabParameter( root, "name");
203  if( string == NULL)
204    {
205      PRINTF(2)("GameWorld is missing a proper 'name'\n");
206      this->setName("Unknown");
207    }
208  else
209    {
210      this->setName(string);
211    }
212
213
214
215    this->gameWorldData->loadGUI(root);
216
217
218    this->gameWorldData->loadWorldEntities(root);
219
220    //////////////////////////////
221    // LOADING ADDITIONAL STUFF //
222    //////////////////////////////
223
224    LoadParamXML(root, "LightManager", LightManager::getInstance(), LightManager, loadParams);
225
226   LoadParamXML(root, "ParticleEngine", ParticleEngine::getInstance(), ParticleEngine, loadParams);
227//   LoadParamXML(root, "PhysicsEngine", PhysicsEngine::getInstance(), PhysicsEngine, loadParams);
228
229  // free the XML data
230
231  delete XMLDoc;
232  /* GENERIC LOADING PROCESS FINISHED */
233
234
235
236
237
238//   //localCamera->setParent(TrackNode::getInstance());
239//  tn->addChild(this->localCamera);
240  this->gameWorldData->localCamera->setClipRegion(1, 10000.0);
241//  localCamera->lookAt(playable);
242//  this->localPlayer->setParentMode(PNODE_ALL);
243  if (this->gameWorldData->sky != NULL)
244  {
245    this->gameWorldData->localCamera->addChild(this->gameWorldData->sky);
246  }
247  SoundEngine::getInstance()->setListener(this->gameWorldData->localCamera);
248
249  /* some static stuff*/
250
251  this->music = NULL;
252  //(OggPlayer*)ResourceManager::getInstance()->load("sound/00-luke_grey_-_hypermode.ogg", OGG, RP_LEVEL);
253  //music->playback();
254
255  /* update the object position before game start - so there are no wrong coordinates used in the first processing */
256  PNode::getNullParent()->updateNode (0.001f);
257  PNode::getNullParent()->updateNode (0.001f);
258
259  this->releaseLoadScreen();
260}
261
262
263/**
264 *  unload the data of this GameWorld
265 */
266ErrorMessage GameWorld::unloadData()
267{
268  delete this->shell;
269  PRINTF(3)("GameWorld::~GameWorld() - unloading the current GameWorld\n");
270
271  // delete all the initialized Engines.
272  FastFactory::flushAll(true);
273  delete LightManager::getInstance();
274  delete ParticleEngine::getInstance();
275  delete AnimationPlayer::getInstance();
276  delete PhysicsEngine::getInstance();
277
278  // external engines initialized by the orxonox-class get deleted
279  SoundEngine::getInstance()->flushAllBuffers();
280  SoundEngine::getInstance()->flushAllSources();
281
282  if (State::getObjectManager() == &this->objectManager)
283    State::setObjectManager(NULL);
284  // erease everything that is left.
285  delete PNode::getNullParent();
286
287  //secondary cleanup of PNodes;
288  const std::list<BaseObject*>* nodeList = ClassList::getList(CL_PARENT_NODE);
289  if (nodeList != NULL)
290    while (!nodeList->empty())
291      delete nodeList->front();
292
293  Shader::suspendShader();
294
295  // unload the resources !!
296  ResourceManager::getInstance()->unloadAllByPriority(RP_LEVEL);
297}
298
299
300/**
301 *  starts the GameWorld
302 */
303bool GameWorld::start()
304{
305  this->isPaused = false;
306  this->isRunning = true;
307
308  this->run();
309}
310
311/**
312 *  stops the world.
313
314   This happens, when the player decides to end the Level.
315*/
316bool GameWorld::stop()
317{
318  PRINTF(3)("GameWorld::stop() - got stop signal\n");
319  this->isRunning = false;
320}
321
322/**
323 *  pauses the Game
324*/
325bool GameWorld::pause()
326{
327  this->isPaused = true;
328}
329
330/**
331 *  ends the pause Phase
332*/
333bool GameWorld::resume()
334{
335  this->isPaused = false;
336}
337
338
339/**
340 *  shows the loading screen
341*/
342void GameWorld::displayLoadScreen ()
343{
344  PRINTF(3)("GameWorld::displayLoadScreen - start\n");
345  this->gameWorldData->glmis = new GLMenuImageScreen();
346  this->gameWorldData->glmis->setMaximum(8);
347  PRINTF(3)("GameWorld::displayLoadScreen - end\n");
348}
349
350
351/**
352 * @brief removes the loadscreen, and changes over to the game
353 *
354 * @todo take out the delay
355*/
356void GameWorld::releaseLoadScreen ()
357{
358  PRINTF(3)("GameWorld::releaseLoadScreen - start\n");
359  this->gameWorldData->glmis->setValue(this->gameWorldData->glmis->getMaximum());
360  PRINTF(3)("GameWorld::releaseLoadScreen - end\n");
361  delete this->gameWorldData->glmis;
362}
363
364
365/**
366 *  synchronize local data with remote data
367*/
368void GameWorld::synchronize ()
369{
370  // Get remote input
371  // Update synchronizables
372/*  NetworkManager::getInstance()->synchronize();*/
373}
374
375
376/**
377 *  run all input processing
378
379   the command node is the central input event dispatcher. the node uses the even-queue from
380   sdl and has its own event-passing-queue.
381*/
382void GameWorld::handleInput ()
383{
384  EventHandler::getInstance()->process();
385
386  // remoteinput
387}
388
389void GameWorld::tick(std::list<WorldEntity*> entityList, float dt)
390{
391  std::list<WorldEntity*>::iterator entity;
392  for (entity = entityList.begin(); entity != entityList.end(); entity++)
393    (*entity)->tick(dt);
394
395}
396
397/**
398 *  advance the timeline
399
400   this calculates the time used to process one frame (with all input handling, drawing, etc)
401   the time is mesured in ms and passed to all world-entities and other classes that need
402   a heart-beat.
403*/
404void GameWorld::tick ()
405{
406  Uint32 currentFrame = SDL_GetTicks();
407  if( !this->isPaused)
408    {
409      this->dt = currentFrame - this->lastFrame;
410
411      if( this->dt > 10)
412        {
413          float fps = 1000/dt;
414
415          // temporary, only for showing how fast the text-engine is
416          char tmpChar[20];
417          sprintf(tmpChar, "fps: %4.0f", fps);
418        }
419      else
420        {
421          /* the frame-rate is limited to 100 frames per second, all other things are for
422             nothing.
423          */
424          PRINTF(3)("fps = 1000 - frame rate is adjusted\n");
425          SDL_Delay(10-dt);
426          this->dt = 10;
427        }
428
429      this->dtS = (float)this->dt / 1000.0 * this->speed;
430      this->gameTime += this->dtS;
431
432      this->tick(this->objectManager.getObjectList(OM_DEAD_TICK), this->dtS);
433      this->tick(this->objectManager.getObjectList(OM_COMMON), this->dtS);
434      this->tick(this->objectManager.getObjectList(OM_GROUP_00), this->dtS);
435      this->tick(this->objectManager.getObjectList(OM_GROUP_01), this->dtS);
436      this->tick(this->objectManager.getObjectList(OM_GROUP_01_PROJ), this->dtS);
437
438      /* update tick the rest */
439      this->gameWorldData->localCamera->tick(this->dtS);
440      // tick the engines
441      AnimationPlayer::getInstance()->tick(this->dtS);
442//      if (this->cycle > 5)
443        PhysicsEngine::getInstance()->tick(this->dtS);
444
445      ParticleEngine::getInstance()->tick(this->dtS);
446
447
448      /** actualy the Graphics Engine should tick the world not the other way around...
449         but since we like the things not too complicated we got it this way around
450         until there is need or time to do it the other way around.
451         @todo: GraphicsEngine ticks world: separation of processes and data...
452
453        bensch: in my opinion the GraphicsEngine could draw the world, but not tick it,
454         beceause graphics have nothing(or at least not much) to do with Motion.
455      */
456      GraphicsEngine::getInstance()->tick(this->dtS);
457    }
458  this->lastFrame = currentFrame;
459}
460
461
462/**
463 *  this function gives the world a consistant state
464
465   after ticking (updating the world state) this will give a constistant
466   state to the whole system.
467*/
468void GameWorld::update()
469{
470  GraphicsEngine::getInstance()->update(this->dtS);
471  PNode::getNullParent()->updateNode (this->dtS);
472  SoundEngine::getInstance()->update();
473  //music->update();
474}
475
476
477void GameWorld::collide()
478{
479  CDEngine::getInstance()->checkCollisions(this->objectManager.getObjectList(OM_GROUP_00),
480                                            this->objectManager.getObjectList(OM_GROUP_01_PROJ));
481  CDEngine::getInstance()->checkCollisions(this->objectManager.getObjectList(OM_GROUP_01),
482                                            this->objectManager.getObjectList(OM_COMMON));
483}
484
485/**
486 *  render the current frame
487
488   clear all buffers and draw the world
489*/
490void GameWorld::display ()
491{
492  // clear buffer
493  glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
494  // set camera
495  this->gameWorldData->localCamera->apply ();
496  // draw world
497  this->draw();
498  // draw HUD
499  /** @todo draw HUD */
500  // flip buffers
501  GraphicsEngine::swapBuffers();
502  //SDL_Surface* screen = Orxonox::getInstance()->getScreen ();
503  //SDL_Flip (screen);
504}
505
506
507/**
508 *  runs through all entities calling their draw() methods
509 */
510void GameWorld::draw ()
511{
512  GraphicsEngine* engine = GraphicsEngine::getInstance();
513  engine->draw(State::getObjectManager()->getObjectList(OM_ENVIRON_NOTICK));
514  engine->draw(State::getObjectManager()->getObjectList(OM_ENVIRON));
515  engine->draw(State::getObjectManager()->getObjectList(OM_COMMON));
516  engine->draw(State::getObjectManager()->getObjectList(OM_GROUP_00));
517  engine->draw(State::getObjectManager()->getObjectList(OM_GROUP_01));
518  engine->draw(State::getObjectManager()->getObjectList(OM_GROUP_01_PROJ));
519
520   if( unlikely( this->showBV))  // to draw the bounding boxes of the objects at level 2 for debug purp
521   {
522     CDEngine* engine = CDEngine::getInstance();
523     engine->drawBV(State::getObjectManager()->getObjectList(OM_ENVIRON_NOTICK));
524     engine->drawBV(State::getObjectManager()->getObjectList(OM_ENVIRON));
525     engine->drawBV(State::getObjectManager()->getObjectList(OM_COMMON));
526     engine->drawBV(State::getObjectManager()->getObjectList(OM_GROUP_00));
527     engine->drawBV(State::getObjectManager()->getObjectList(OM_GROUP_01));
528     engine->drawBV(State::getObjectManager()->getObjectList(OM_GROUP_01_PROJ));
529   }
530
531//   {
532//     if( entity->isVisible() ) entity->draw();
533  //FIXME
534//     entity = iterator->nextElement();
535//   }
536
537  ParticleEngine::getInstance()->draw();
538
539  if (unlikely(this->showPNodes))
540    PNode::getNullParent()->debugDraw(0);
541
542  engine->draw();
543  //TextEngine::getInstance()->draw();
544}
545
546
547/**
548 * \brief main loop of the world: executing all world relevant function
549 *
550 * in this loop we synchronize (if networked), handle input events, give the heart-beat to
551 * all other member-entities of the world (tick to player, enemies etc.), checking for
552 * collisions drawing everything to the screen.
553 */
554void GameWorld::run()
555{
556  this->lastFrame = SDL_GetTicks ();
557  PRINTF(3)("GameWorld::mainLoop() - Entering main loop\n");
558
559  while( this->isRunning) /* @todo implement pause */
560  {
561    ++this->cycle;
562      // Network
563    this->synchronize ();
564      // Process input
565    this->handleInput ();
566    if( !this->isRunning)
567      break;
568      // Process time
569    this->tick ();
570      // Process collision
571    this->collide ();
572      // Update the state
573    this->update ();
574      // Draw
575    this->display ();
576  }
577
578  PRINTF(3)("GameWorld::mainLoop() - Exiting the main loop\n");
579}
580
581
582
583/**
584 *  add and spawn a new entity to this world
585 * @param entity to be added
586*/
587// void GameWorld::spawn(WorldEntity* entity)
588// {
589// //   this->entities->add (entity);
590//   entity->postSpawn ();
591// }
592
593/**
594 *  sets the track path of this world
595 * @param name the name of the path
596 */
597void GameWorld::setPath( const char* name)
598{
599  if (this->path)
600    delete this->path;
601  if (ResourceManager::isFile(name))
602  {
603    this->path = new char[strlen(name)+1];
604    strcpy(this->path, name);
605  }
606  else
607    {
608      this->path = new char[strlen(ResourceManager::getInstance()->getDataDir()) + strlen(name) +1];
609      sprintf(this->path, "%s%s", ResourceManager::getInstance()->getDataDir(), name);
610    }
611}
612
613
614
615
616
617
618
619GameWorldData::GameWorldData()
620{
621  this->localPlayer = NULL;
622  this->localCamera = NULL;
623
624  this->glmis = NULL;
625
626  this->localCamera = NULL;
627  this->localPlayer = NULL;
628  this->sky = NULL;
629  this->terrain = NULL;
630
631}
632
633
634GameWorldData::~GameWorldData()
635{
636  if( this->localPlayer)
637    delete this->localPlayer;
638}
639
640
641
642ErrorMessage GameWorldData::loadData(TiXmlElement* root)
643{}
644
645
646
647
648ErrorMessage GameWorldData::loadGUI(TiXmlElement* root)
649{
650  ////////////////
651  // LOADSCREEN //
652  ////////////////
653  TiXmlElement* element = root->FirstChildElement("LoadScreen");
654  if( element == NULL)
655  {
656    PRINTF(2)("no LoadScreen specified, loading default\n");
657
658    glmis->setBackgroundImage("pictures/load_screen.jpg");
659    this->glmis->setMaximum(8);
660    this->glmis->draw();
661  }
662  else
663  {
664    this->glmis->loadParams(element);
665    this->glmis->draw();
666  }
667  this->glmis->draw();
668
669}
670
671
672ErrorMessage GameWorldData::loadWorldEntities(TiXmlElement* root)
673{
674  ////////////////////////
675  // find WorldEntities //
676  ////////////////////////
677
678  TiXmlElement* element = root->FirstChildElement("WorldEntities");
679
680  if( element == NULL)
681  {
682    PRINTF(1)("GameWorld is missing 'WorldEntities'\n");
683  }
684  else
685  {
686    element = element->FirstChildElement();
687      // load Players/Objects/Whatever
688    PRINTF(4)("Loading WorldEntities\n");
689    while( element != NULL)
690    {
691      BaseObject* created = Factory::fabricate(element);
692      if( created != NULL )
693        printf("Created a %s: %s\n", created->getClassName(), created->getName());
694
695
696          //todo do this more elegant
697      if( element->Value() != NULL && !strcmp( element->Value(), "SkyBox"))
698        this->sky = dynamic_cast<WorldEntity*>(created);
699      if( element->Value() != NULL && !strcmp( element->Value(), "Terrain"))
700      {
701        this->terrain = dynamic_cast<Terrain*>(created);
702        CDEngine::getInstance()->setTerrain(terrain);
703      }
704      element = element->NextSiblingElement();
705      this->glmis->step(); //! @todo temporary
706    }
707    PRINTF(4)("Done loading WorldEntities\n");
708  }
709
710    // Create a Player
711  this->localPlayer = new Player();
712
713  Playable* playable;
714  const list<BaseObject*>* playableList = ClassList::getList(CL_PLAYABLE);
715  if (playableList != NULL)
716  {
717    playable = dynamic_cast<Playable*>(playableList->front());
718    this->localPlayer->setControllable(playable);
719  }
720}
721
722
723ErrorMessage GameWorldData::loadScene(TiXmlElement* root)
724{}
725
Note: See TracBrowser for help on using the repository browser.