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
Line 
1
2
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.
12
13   ### File Specific:
14   main-programmer: Patrick Boenzli
15   co-programmer: ...
16*/
17
18#include "game_loader.h"
19
20#include "shell_command.h"
21#include "campaign.h"
22#include "world.h"
23#include "orxonox.h"
24#include "camera.h"
25#include "vector.h"
26#include "resource_manager.h"
27#include "factory.h"
28#include "event.h"
29#include "event_handler.h"
30#include <string.h>
31
32
33using namespace std;
34
35
36SHELL_COMMAND(quit, GameLoader, stop)
37    ->describe("quits the game")
38    ->setAlias("orxoquit");
39
40
41GameLoader* GameLoader::singletonRef = NULL;
42
43
44/**
45 *  simple constructor
46*/
47GameLoader::GameLoader ()
48{
49  this->setClassID(CL_GAME_LOADER, "GameLoader");
50  this->setName("GameLoader");
51
52}
53
54
55/**
56 *  simple deconstructor
57*/
58GameLoader::~GameLoader ()
59{
60  if( this->currentCampaign)
61    delete this->currentCampaign;
62  this->currentCampaign = NULL;
63}
64
65
66/**
67 *  this class is a singleton class
68 * @returns an instance of itself
69
70   if you are unsure about singleton classes, check the theory out on the internet :)
71*/
72GameLoader* GameLoader::getInstance()
73{
74  if(singletonRef == NULL)
75    singletonRef = new GameLoader();
76  return singletonRef;
77}
78
79/**
80 *  initializes the GameLoader
81*/
82ErrorMessage GameLoader::init()
83{
84  if(this->currentCampaign != NULL)
85    this->currentCampaign->init();
86
87  this->eventHandler = EventHandler::getInstance();
88  this->eventHandler->subscribe(this, ES_GAME, KeyMapper::PEV_PAUSE);
89  this->eventHandler->subscribe(this, ES_ALL, KeyMapper::PEV_QUIT);
90  this->eventHandler->subscribe(this, ES_GAME, KeyMapper::PEV_NEXT_WORLD);
91  this->eventHandler->subscribe(this, ES_GAME, KeyMapper::PEV_PREVIOUS_WORLD);
92}
93
94
95/**
96 *  reads a campaign definition file into a campaign class
97 * @param fileName to be loaded
98 * @returns the loaded campaign
99
100   this will interprete the map/campaign files and recursivly load a tree of worlds/campaigns
101*/
102ErrorMessage GameLoader::loadCampaign(const char* fileName)
103{
104  ErrorMessage errorCode;
105  char* campaignName = ResourceManager::getFullName(fileName);
106  if (campaignName)
107    {
108      this->currentCampaign = this->fileToCampaign(campaignName);
109      delete[] campaignName;
110    }
111//   World* world0 = new World(DEBUG_WORLD_0);
112//   world0->setNextStoryID(WORLD_ID_GAMEEND);
113//   this->currentCampaign->addEntity(world0, WORLD_ID_2);
114}
115
116/**
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.
120*/
121ErrorMessage GameLoader::loadDebugCampaign(Uint32 campaignID)
122{
123  switch(campaignID)
124    {
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.
130      */
131    case DEBUG_CAMPAIGN_0:
132      {
133        Campaign* debugCampaign = new Campaign();
134
135        World* world0 = new World(DEBUG_WORLD_0);
136        world0->setNextStoryID(WORLD_ID_1);
137        debugCampaign->addEntity(world0, WORLD_ID_0);
138
139        World* world1 = new World(DEBUG_WORLD_1);
140        world1->setNextStoryID(WORLD_ID_2);
141        debugCampaign->addEntity(world1, WORLD_ID_1);
142
143        World* world2 = new World(DEBUG_WORLD_2);
144        world2->setNextStoryID(WORLD_ID_GAMEEND);
145        debugCampaign->addEntity(world2, WORLD_ID_2);
146
147        this->currentCampaign = debugCampaign;
148        break;
149      }
150    }
151}
152
153
154/**
155  *  starts the current entity
156  * @returns error code if this action has caused a error
157*/
158ErrorMessage GameLoader::start()
159{
160  if(this->currentCampaign != NULL)
161    this->currentCampaign->start();
162}
163
164
165/**
166  *  stops the current entity
167  * @returns error code if this action has caused a error
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*/
175void GameLoader::stop()
176{
177  if(this->currentCampaign != NULL)
178    this->currentCampaign->stop();
179}
180
181
182/**
183  *  pause the current entity
184  * @returns error code if this action has caused a error
185
186    this pauses the current entity or passes this call forth to the running entity.
187*/
188ErrorMessage GameLoader::pause()
189{
190  this->isPaused = true;
191  if(this->currentCampaign != NULL)
192    this->currentCampaign->pause();
193}
194
195
196/**
197  *  resumes a pause
198  * @returns error code if this action has caused a error
199
200    this resumess the current entity or passes this call forth to the running entity.
201*/
202ErrorMessage GameLoader::resume()
203{
204  this->isPaused = false;
205  if(this->currentCampaign != NULL)
206    this->currentCampaign->resume();
207}
208
209
210/**
211 *  release the mem ATTENTION: not implemented
212 */
213ErrorMessage GameLoader::destroy()
214{
215
216}
217
218
219/**
220 *  reads a campaign definition file into a campaign class
221 * @param fileName to be loaded
222 * @returns the loaded campaign
223
224   this will interprete the map/campaign files and recursivly load a tree of worlds/campaigns
225*/
226Campaign* GameLoader::fileToCampaign(const char* fileName)
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  */
232
233  if( fileName == NULL)
234    {
235      PRINTF(2)("No filename specified for loading");
236      return NULL;
237    }
238
239  TiXmlDocument* XMLDoc = new TiXmlDocument( fileName);
240  // load the campaign document
241  if( !XMLDoc->LoadFile())
242    {
243      // report an error
244      PRINTF(1)("Could not load XML File %s: %s @ %d:%d\n", fileName, XMLDoc->ErrorDesc(), XMLDoc->ErrorRow(), XMLDoc->ErrorCol());
245      delete XMLDoc;
246      return NULL;
247    }
248
249  // check basic validity
250  TiXmlElement* root = XMLDoc->RootElement();
251  assert( root != NULL);
252
253  if( strcmp( root->Value(), "Campaign"))
254    {
255      // report an error
256      PRINTF(2)("Specified XML File is not an orxonox campaign file (Campaign element missing)\n");
257      delete XMLDoc;
258      return NULL;
259    }
260
261  // construct campaign
262  Campaign* c = new Campaign( root);
263
264  // free the XML data
265  delete XMLDoc;
266
267  return c;
268}
269
270
271/**
272 *  handle keyboard commands
273 * @param event the event to handle
274*/
275void GameLoader::process(const Event& event)
276{
277  if( event.type == KeyMapper::PEV_NEXT_WORLD)
278    {
279      if( likely(event.bPressed))
280        {
281          this->nextLevel();
282        }
283    }
284  else if( event.type == KeyMapper::PEV_PREVIOUS_WORLD)
285    {
286      if( likely(event.bPressed))
287        {
288          this->previousLevel();
289        }
290    }
291  else if( event.type == KeyMapper::PEV_PAUSE)
292    {
293      if( likely(event.bPressed))
294        {
295          if(this->isPaused)
296            this->resume();
297          else
298            this->pause();
299        }
300    }
301  else if( event.type == KeyMapper::PEV_QUIT)
302    {
303      if( event.bPressed) this->stop();
304    }
305}
306
307
308/**
309  \brief this changes to the next level
310*/
311void GameLoader::nextLevel()
312{
313  if(this->currentCampaign != NULL)
314    this->currentCampaign->nextLevel();
315}
316
317
318/**
319  \brief change to the previous level - not implemented
320
321  this propably useless
322*/
323void GameLoader::previousLevel()
324{
325  if(this->currentCampaign != NULL)
326    this->currentCampaign->previousLevel();
327}
328
329/**
330 *  load a StoryEntity
331 * @param element a XMLElement containing all the needed info
332*/
333BaseObject* GameLoader::fabricate(const TiXmlElement* element)
334{
335  assert( element != NULL);
336
337  if( Factory::getFirst() == NULL)
338    {
339      PRINTF(1)("GameLoader does not know any factories, fabricate() failed\n");
340      return NULL;
341    }
342
343  if( element->Value() != NULL)
344    {
345      PRINTF(4)("Attempting fabrication of a '%s'\n", element->Value());
346      BaseObject* b = Factory::getFirst()->fabricate( element);
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());
351      return b;
352    }
353
354  PRINTF(2)("Fabricate failed, TiXmlElement did not contain a value\n");
355
356  return NULL;
357}
Note: See TracBrowser for help on using the repository browser.