Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/util/loading/game_loader.cc @ 5242

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

orxonox/trunk: first fruits of valgrind…. delete[] are fine now :)

File size: 8.3 KB
RevLine 
[2636]1
2
[4597]3/*
[2636]4   orxonox - the future of 3D-vertical-scrollers
5
6   Copyright (C) 2004 orx
7
8   This program is free software; you can redistribute it and/or modify
9   it under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 2, or (at your option)
11   any later version.
12
13   ### File Specific:
14   main-programmer: Patrick Boenzli
15   co-programmer: ...
16*/
17
18#include "game_loader.h"
[5139]19
20#include "shell_command.h"
[2636]21#include "campaign.h"
22#include "world.h"
23#include "orxonox.h"
24#include "camera.h"
25#include "vector.h"
[4094]26#include "resource_manager.h"
[4010]27#include "factory.h"
[4410]28#include "event.h"
29#include "event_handler.h"
[2636]30#include <string.h>
31
32
33using namespace std;
34
35
[5195]36SHELL_COMMAND(quit, GameLoader, stop)
37    ->describe("quits the game")
38    ->setAlias("orxoquit");
[2636]39
[5162]40
41GameLoader* GameLoader::singletonRef = NULL;
42
43
[4445]44/**
[4836]45 *  simple constructor
[4487]46*/
[4597]47GameLoader::GameLoader ()
[4017]48{
[4597]49  this->setClassID(CL_GAME_LOADER, "GameLoader");
50  this->setName("GameLoader");
[5139]51
[4017]52}
[2636]53
54
[4445]55/**
[4836]56 *  simple deconstructor
[4487]57*/
[4816]58GameLoader::~GameLoader ()
59{
60  if( this->currentCampaign)
61    delete this->currentCampaign;
62  this->currentCampaign = NULL;
63}
[2636]64
65
[3225]66/**
[4836]67 *  this class is a singleton class
68 * @returns an instance of itself
[3225]69
70   if you are unsure about singleton classes, check the theory out on the internet :)
71*/
[2636]72GameLoader* GameLoader::getInstance()
73{
74  if(singletonRef == NULL)
75    singletonRef = new GameLoader();
76  return singletonRef;
77}
78
[4487]79/**
[4836]80 *  initializes the GameLoader
[4487]81*/
[3222]82ErrorMessage GameLoader::init()
[2636]83{
84  if(this->currentCampaign != NULL)
85    this->currentCampaign->init();
[4411]86
87  this->eventHandler = EventHandler::getInstance();
[5093]88  this->eventHandler->subscribe(this, ES_GAME, KeyMapper::PEV_PAUSE);
[4411]89  this->eventHandler->subscribe(this, ES_ALL, KeyMapper::PEV_QUIT);
[5093]90  this->eventHandler->subscribe(this, ES_GAME, KeyMapper::PEV_NEXT_WORLD);
91  this->eventHandler->subscribe(this, ES_GAME, KeyMapper::PEV_PREVIOUS_WORLD);
[2636]92}
93
94
[3225]95/**
[4836]96 *  reads a campaign definition file into a campaign class
97 * @param fileName to be loaded
98 * @returns the loaded campaign
[3225]99
100   this will interprete the map/campaign files and recursivly load a tree of worlds/campaigns
101*/
[4487]102ErrorMessage GameLoader::loadCampaign(const char* fileName)
[2636]103{
[3222]104  ErrorMessage errorCode;
[4487]105  char* campaignName = ResourceManager::getFullName(fileName);
[4216]106  if (campaignName)
[4094]107    {
108      this->currentCampaign = this->fileToCampaign(campaignName);
[5208]109      delete[] campaignName;
[4094]110    }
[4816]111//   World* world0 = new World(DEBUG_WORLD_0);
112//   world0->setNextStoryID(WORLD_ID_GAMEEND);
113//   this->currentCampaign->addEntity(world0, WORLD_ID_2);
[2636]114}
115
[3225]116/**
[4836]117 *  loads a debug campaign for test purposes only.
118 * @param campaignID the identifier of the campaign.
119 * @returns error message if not able to do so.
[3225]120*/
[3222]121ErrorMessage GameLoader::loadDebugCampaign(Uint32 campaignID)
[2636]122{
123  switch(campaignID)
124    {
[4597]125      /*
126         Debug Level 0: Debug level used to test the base frame work.
127         As you can see, all storyentity data is allocated before game
128         start. the storyentity will load themselfs shortly before start
129         through the StoryEntity::init() funtion.
[3629]130      */
[2636]131    case DEBUG_CAMPAIGN_0:
132      {
[4597]133        Campaign* debugCampaign = new Campaign();
[3220]134
[4597]135        World* world0 = new World(DEBUG_WORLD_0);
136        world0->setNextStoryID(WORLD_ID_1);
137        debugCampaign->addEntity(world0, WORLD_ID_0);
[3220]138
[4597]139        World* world1 = new World(DEBUG_WORLD_1);
140        world1->setNextStoryID(WORLD_ID_2);
141        debugCampaign->addEntity(world1, WORLD_ID_1);
[2636]142
[4597]143        World* world2 = new World(DEBUG_WORLD_2);
144        world2->setNextStoryID(WORLD_ID_GAMEEND);
145        debugCampaign->addEntity(world2, WORLD_ID_2);
[3727]146
[4597]147        this->currentCampaign = debugCampaign;
148        break;
[2636]149      }
150    }
151}
152
[4443]153
[4597]154/**
[4836]155  *  starts the current entity
156  * @returns error code if this action has caused a error
[4443]157*/
[3222]158ErrorMessage GameLoader::start()
[2636]159{
160  if(this->currentCampaign != NULL)
161    this->currentCampaign->start();
162}
163
164
[4597]165/**
[4836]166  *  stops the current entity
167  * @returns error code if this action has caused a error
[4443]168
169    ATTENTION: this function shouldn't call other functions, or if so, they must return
170    after finishing. If you ignore or forget to do so, the current entity is not able to
171    terminate and it will run in the background or the ressources can't be freed or even
172    worse: are freed and the program will end in a segmentation fault!
173    hehehe, have ya seen it... :)
174*/
[5139]175void GameLoader::stop()
[2636]176{
177  if(this->currentCampaign != NULL)
178    this->currentCampaign->stop();
179}
180
181
[4597]182/**
[4836]183  *  pause the current entity
184  * @returns error code if this action has caused a error
[4443]185
186    this pauses the current entity or passes this call forth to the running entity.
187*/
[3222]188ErrorMessage GameLoader::pause()
[2636]189{
190  this->isPaused = true;
191  if(this->currentCampaign != NULL)
192    this->currentCampaign->pause();
193}
194
195
[4597]196/**
[4836]197  *  resumes a pause
198  * @returns error code if this action has caused a error
[4443]199
200    this resumess the current entity or passes this call forth to the running entity.
201*/
[3222]202ErrorMessage GameLoader::resume()
[2636]203{
204  this->isPaused = false;
205  if(this->currentCampaign != NULL)
206    this->currentCampaign->resume();
207}
208
[4443]209
[3225]210/**
[4836]211 *  release the mem ATTENTION: not implemented
[3225]212 */
213ErrorMessage GameLoader::destroy()
[4487]214{
[2636]215
[4487]216}
[2636]217
[4487]218
[3225]219/**
[4836]220 *  reads a campaign definition file into a campaign class
221 * @param fileName to be loaded
222 * @returns the loaded campaign
[3225]223
224   this will interprete the map/campaign files and recursivly load a tree of worlds/campaigns
225*/
[4487]226Campaign* GameLoader::fileToCampaign(const char* fileName)
[2636]227{
228  /* do not entirely load the campaign. just the current world
229     before start of each world, it has to be initialized so it
230     can load everything it needs into memory then.
231  */
[4597]232
[4487]233  if( fileName == NULL)
[4010]234    {
[4113]235      PRINTF(2)("No filename specified for loading");
[4010]236      return NULL;
237    }
[4597]238
[4487]239  TiXmlDocument* XMLDoc = new TiXmlDocument( fileName);
[4010]240  // load the campaign document
241  if( !XMLDoc->LoadFile())
242    {
243      // report an error
[4487]244      PRINTF(1)("Could not load XML File %s: %s @ %d:%d\n", fileName, XMLDoc->ErrorDesc(), XMLDoc->ErrorRow(), XMLDoc->ErrorCol());
[4010]245      delete XMLDoc;
246      return NULL;
247    }
[4597]248
[4010]249  // check basic validity
250  TiXmlElement* root = XMLDoc->RootElement();
251  assert( root != NULL);
[4597]252
[4010]253  if( strcmp( root->Value(), "Campaign"))
254    {
255      // report an error
[4113]256      PRINTF(2)("Specified XML File is not an orxonox campaign file (Campaign element missing)\n");
[4010]257      delete XMLDoc;
258      return NULL;
259    }
[4597]260
[4010]261  // construct campaign
262  Campaign* c = new Campaign( root);
[4597]263
[4010]264  // free the XML data
265  delete XMLDoc;
[4496]266
[4010]267  return c;
[2636]268}
269
270
271/**
[4836]272 *  handle keyboard commands
273 * @param event the event to handle
[2636]274*/
[4410]275void GameLoader::process(const Event& event)
276{
277  if( event.type == KeyMapper::PEV_NEXT_WORLD)
278    {
[4597]279      if( likely(event.bPressed))
280        {
281          this->nextLevel();
282        }
[4410]283    }
284  else if( event.type == KeyMapper::PEV_PREVIOUS_WORLD)
285    {
286      if( likely(event.bPressed))
[4597]287        {
288          this->previousLevel();
289        }
[4410]290    }
291  else if( event.type == KeyMapper::PEV_PAUSE)
292    {
293      if( likely(event.bPressed))
[4597]294        {
295          if(this->isPaused)
296            this->resume();
297          else
298            this->pause();
299        }
[4410]300    }
301  else if( event.type == KeyMapper::PEV_QUIT)
302    {
303      if( event.bPressed) this->stop();
304    }
305}
306
[4443]307
[4487]308/**
[3225]309  \brief this changes to the next level
310*/
[2636]311void GameLoader::nextLevel()
312{
313  if(this->currentCampaign != NULL)
314    this->currentCampaign->nextLevel();
315}
316
[3225]317
[4487]318/**
[3225]319  \brief change to the previous level - not implemented
320
321  this propably useless
322*/
[2636]323void GameLoader::previousLevel()
324{
325  if(this->currentCampaign != NULL)
326    this->currentCampaign->previousLevel();
327}
[4010]328
329/**
[4836]330 *  load a StoryEntity
331 * @param element a XMLElement containing all the needed info
[4010]332*/
[4598]333BaseObject* GameLoader::fabricate(const TiXmlElement* element)
[4010]334{
[4114]335  assert( element != NULL);
[4597]336
[4739]337  if( Factory::getFirst() == NULL)
[4114]338    {
339      PRINTF(1)("GameLoader does not know any factories, fabricate() failed\n");
340      return NULL;
341    }
[4597]342
[4114]343  if( element->Value() != NULL)
344    {
345      PRINTF(4)("Attempting fabrication of a '%s'\n", element->Value());
[4739]346      BaseObject* b = Factory::getFirst()->fabricate( element);
[4597]347      if( b == NULL)
348        PRINTF(2)("Failed to fabricate a '%s'\n", element->Value());
349      else
350        PRINTF(4)("Successfully fabricated a '%s'\n", element->Value());
[4114]351      return b;
352    }
[4597]353
[4114]354  PRINTF(2)("Fabricate failed, TiXmlElement did not contain a value\n");
[4597]355
[4114]356  return NULL;
[4010]357}
Note: See TracBrowser for help on using the repository browser.