Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: Element2D added → will be moved to lib/graphics afterwards
ProtoClass update
EventListeners do not have to be unsubscribed externally, but still one listener won't unsubscribe

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