Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: registered 'quit' from GameLoader

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