Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/story_entities/simple_game_menu.cc @ 7910

Last change on this file since 7910 was 7868, checked in by bensch, 18 years ago

trunk: merge Check in the Event-changes:
r7867 | bensch | 2006-05-26 13:19:46 +0200 (Fri, 26 May 2006) | 1 line

Events better subscribed


r7866 | bensch | 2006-05-26 13:11:10 +0200 (Fri, 26 May 2006) | 1 line

Events are subscribed at the EventListener, and not the EventHandler

File size: 15.9 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
14*/
15
16#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_WORLD
17
18
19#include "simple_game_menu.h"
20
21#include "event_handler.h"
22
23#include "state.h"
24#include "class_list.h"
25
26#include "util/loading/load_param.h"
27#include "fast_factory.h"
28#include "util/loading/factory.h"
29
30#include "p_node.h"
31#include "world_entity.h"
32#include "elements/image_entity.h"
33#include "terrain.h"
34#include "camera.h"
35
36#include "graphics_engine.h"
37#include "object_manager.h"
38#include "sound_engine.h"
39#include "sound_source.h"
40
41#include "cd_engine.h"
42
43
44using namespace std;
45
46
47//! This creates a Factory to fabricate a SimpleGameMenu
48CREATE_FACTORY(SimpleGameMenu, CL_SIMPLE_GAME_MENU);
49
50
51
52SimpleGameMenu::SimpleGameMenu(const TiXmlElement* root)
53  : GameWorld()
54{
55  this->setClassID(CL_SIMPLE_GAME_MENU, "SimpleGameMenu");
56  this->setName("SimpleGameMenu uninitialized");
57
58  this->dataTank = new SimpleGameMenuData();
59
60  this->cameraVector = Vector(50.0, 0.0, 0.0);
61  this->menuLayers.push_back(MenuLayer());
62  this->menuLayers.push_back(MenuLayer());
63
64  this->layerIndex = 0;
65  this->menuSelectedIndex = 0;
66  this->selectorSource = NULL;
67
68  if (root != NULL)
69    this->loadParams(root);
70
71  State::setMenuID(this->getNextStoryID());
72}
73
74
75/**
76 *  @brief remove the SimpleGameMenu from memory
77 *
78 *  delete everything explicitly, that isn't contained in the parenting tree!
79 *  things contained in the tree are deleted automaticaly
80 */
81SimpleGameMenu::~SimpleGameMenu ()
82{
83  PRINTF(3)("SimpleGameMenu::~SimpleGameMenu() - deleting current world\n");
84
85  if( this->dataTank)
86    delete this->dataTank;
87}
88
89
90/**
91 * @brief loads the parameters of a SimpleGameMenu from an XML-element
92 * @param root the XML-element to load from
93 */
94void SimpleGameMenu::loadParams(const TiXmlElement* root)
95{
96  /* skip the GameWorld, since it does not define any useful loadParams for this class */
97  //static_cast<GameWorld*>(this)->loadParams(root);
98  GameWorld::loadParams(root);
99
100  PRINTF(4)("Loaded SimpleGameMenu specific stuff\n");
101}
102
103
104/**
105 * @brief this is executed just before load
106 *
107 * since the load function sometimes needs data, that has been initialized
108 * before the load and after the proceeding storyentity has finished
109 */
110ErrorMessage SimpleGameMenu::init()
111{
112  /* call underlying init funciton */
113  GameWorld::init();
114
115  this->subscribeEvent(ES_MENU, SDLK_UP);
116  this->subscribeEvent(ES_MENU, SDLK_DOWN);
117  this->subscribeEvent(ES_MENU, SDLK_RETURN);
118  this->subscribeEvent(ES_MENU, SDLK_SPACE);
119  this->subscribeEvent(ES_MENU, SDLK_ESCAPE);
120
121  this->dataTank->localCamera->setRelCoor(this->cameraVector);
122
123  GraphicsEngine::getInstance()->displayFPS(false);
124
125  this->layerIndex = 0;
126  this->menuSelectedIndex = 0;
127}
128
129
130/**
131 * @brief load the data
132 */
133ErrorMessage SimpleGameMenu::loadData()
134{
135  GameWorld::loadData();
136
137  if (this->dataXML != NULL)
138  {
139    LoadParam(dataXML, "selector-sound", this, SimpleGameMenu, setSelectorSound);
140
141    TiXmlElement* element = this->dataXML->FirstChildElement("Elements");
142
143
144    if( element == NULL)
145    {
146      PRINTF(1)("SimpleGameMenu is missing 'Elements'\n");
147    }
148    else
149    {
150      element = element->FirstChildElement();
151    // load Players/Objects/Whatever
152      PRINTF(4)("Loading Elements\n");
153      while( element != NULL)
154      {
155        BaseObject* created = Factory::fabricate(element);
156        if( created != NULL )
157        {
158          PRINTF(4)("Created a %s::%s\n", created->getClassName(), created->getName());
159          if (!created->isA(CL_ELEMENT_2D))
160            PRINTF(2)("Error the Created Entity is not an Element2D but an %s::%s\n", created->getClassName(), created->getName());
161        }
162        element = element->NextSiblingElement();
163      }
164      PRINTF(4)("Done loading Elements\n");
165    }
166  }
167
168  /* get the menu list */
169  const std::list<BaseObject*>* imageEntityList = ClassList::getList(CL_IMAGE_ENTITY);
170  std::list<BaseObject*>::const_iterator entity;
171  for (entity = imageEntityList->begin(); entity != imageEntityList->end(); entity++)
172  {
173
174    if( !strcmp("Selector_Menu", (*entity)->getName()))
175    {
176      this->menuSelector = dynamic_cast<ImageEntity*>(*entity);
177      this->menuSelector->setBindNode((const PNode*)NULL);
178    }
179  }
180
181  imageEntityList = ClassList::getList(CL_TEXT_ELEMENT);
182  for (entity = imageEntityList->begin(); entity != imageEntityList->end(); entity++)
183  {
184    if( !strcmp( "StartGame_Menu", (*entity)->getName()))
185    {
186      this->menuStartGame = dynamic_cast<TextElement*>(*entity);
187      this->menuStartGame->setBindNode((const PNode*)NULL);
188      this->menuStartGame->setRelCoor2D(State::getResX() / 2.0f,
189                                        State::getResY() / 2.0f - 60.0f);
190      this->menuLayers[0].menuList.push_back(dynamic_cast<TextElement*>(*entity));
191
192    }
193    else if( !strcmp( "Multiplayer_Menu", (*entity)->getName()))
194    {
195      this->menuStartMultiplayerGame = dynamic_cast<TextElement*>(*entity);
196      this->menuStartMultiplayerGame->setBindNode((const PNode*)NULL);
197      this->menuStartMultiplayerGame->setRelCoor2D(State::getResX() / 2.0f,
198                                                   State::getResY() / 2.0f + ((this->menuLayers[0].menuList.size() -1 ) * 60.0f));
199      this->menuLayers[0].menuList.push_back(dynamic_cast<TextElement*>(*entity));
200    }
201    else if( !strcmp( "Quit_Menu", (*entity)->getName()))
202    {
203      this->menuQuitGame = dynamic_cast<TextElement*>(*entity);
204      this->menuQuitGame->setBindNode((const PNode*)NULL);
205      this->menuQuitGame->setRelCoor2D(State::getResX() / 2.0f,
206                                       State::getResY() / 2.0f + ((this->menuLayers[0].menuList.size() -1 )* 60.0f));
207      this->menuLayers[0].menuList.push_back(dynamic_cast<TextElement*>(*entity));
208    }
209  }
210  this->menuSelected->getNullElement()->update2D(0.1f);
211  this->menuSelectedIndex = 0;
212  this->menuSelected = this->menuLayers[0].menuList[this->menuSelectedIndex];
213  this->sliderTo(this->menuSelected, 0.0f);
214
215
216  // loading the storyentities submenu (singleplayer)
217  const std::list<BaseObject*>* storyEntities = ClassList::getList(CL_STORY_ENTITY);
218  std::list<BaseObject*>::const_iterator it;
219  for( it = storyEntities->begin(); it != storyEntities->end(); it++)
220  {
221    StoryEntity* se = dynamic_cast<StoryEntity*>(*it);
222    if( se->isContainedInMenu())
223    {
224      this->menuLayers[1].storyList.push_back(se);
225
226      // generating menu item
227      TextElement* te = new TextElement();
228      te->setVisibility(false);
229      te->setText(se->getName());
230      te->setRelCoor2D(State::getResX() / 2.0f - 200.0f, State::getResY() / 2.0f + ((this->menuLayers[1].menuList.size() - 2.0f) * 60.0f));
231      this->menuLayers[1].menuList.push_back(te);
232
233      // generating screenshoot item
234      ImageEntity* ie = new ImageEntity();
235      ie->setVisibility(false);
236      ie->setBindNode((const PNode*)NULL);
237      ie->setTexture(se->getMenuScreenshoot());
238      ie->setRelCoor2D(State::getResX() / 2.0f + 250.0f, State::getResY() / 2.0f);
239      ie->setSize2D(140.0f, 105.0f);
240      this->menuLayers[1].screenshootList.push_back(ie);
241    }
242  }
243}
244
245/**
246 * @brief set the Sound to play when switching menu entry.
247 * @param selectorSound the sound to load.
248 */
249void SimpleGameMenu::setSelectorSound(const std::string& selectorSound)
250{
251  this->selectorSource = OrxSound::SoundEngine::getInstance()->createSource(selectorSound, NULL);
252}
253
254ErrorMessage SimpleGameMenu::unloadData()
255{
256  this->unsubscribeEvents(ES_MENU);
257
258  std::vector<MenuLayer>::iterator mit;
259  for(mit = this->menuLayers.begin(); mit != this->menuLayers.end(); mit++)
260  {
261    while(!(*mit).menuList.empty())
262    {
263      delete (*mit).menuList.back();
264      (*mit).menuList.pop_back();
265    }
266
267    (*mit).menuList.clear();
268    (*mit).storyList.clear();
269    (*mit).screenshootList.clear();
270  }
271
272  // delete the SoundSource.
273  if (this->selectorSource != NULL)
274    delete this->selectorSource;
275  this->selectorSource = NULL;
276
277  GameWorld::unloadData();
278}
279
280
281/**
282 * @brief start the menu
283 */
284bool SimpleGameMenu::start()
285{
286  EventHandler::getInstance()->pushState(ES_MENU);
287
288  /* now call the underlying*/
289  GameWorld::start();
290}
291
292
293
294/**
295 * stop the menu
296 */
297bool SimpleGameMenu::stop()
298{
299  EventHandler::getInstance()->popState();
300
301  /* now call the underlying*/
302  GameWorld::stop();
303}
304
305
306/**
307 *  override the standard tick for more functionality
308 */
309void SimpleGameMenu::tick()
310{
311  GameWorld::tick();
312
313  this->animateScene(this->dtS);
314}
315
316
317/**
318 * @brief no collision detection in the menu
319 */
320void SimpleGameMenu::collide()
321{
322//   this->dataTank->localCamera->
323}
324
325
326/**
327 * @brief animate the scene
328 */
329void SimpleGameMenu::animateScene(float dt)
330{
331  Quaternion q(/*0.00005*/ dt * .1, Vector(0.0, 1.0, 0.0));
332  this->cameraVector = q.apply(this->cameraVector);
333  this->dataTank->localCamera->setRelCoor(this->cameraVector);
334  this->dataTank->localCamera->getTarget()->setRelCoorSoft(0,0,0);
335}
336
337
338/**
339 * @brief event dispatcher funciton
340 * @param event the incoming event
341 */
342void SimpleGameMenu::process(const Event &event)
343{
344  /* ----------------- LAYER 1 ---------------*/
345  if( this->layerIndex == 0)
346  {
347    if( event.type == SDLK_RETURN && event.bPressed == true)
348    {
349      if( this->menuSelected == this->menuQuitGame)
350      {
351        this->setNextStoryID(WORLD_ID_GAMEEND);
352        this->stop();
353      }
354      if( this->menuSelected == this->menuStartGame)
355      {
356        // switch to first submenu
357        if( this->menuLayers[1].menuList.size() == 0)
358        {
359          PRINTF(1)("Haven't got any StoryEntities to play!\n");
360          return;
361        }
362
363        this->switchMenuLayer(this->layerIndex, 1);
364      }
365    }
366    if( event.type == SDLK_ESCAPE && event.bPressed == true)
367    {
368      this->setNextStoryID(WORLD_ID_GAMEEND);
369      this->stop();
370    }
371  }  /* ----------------- LAYER 2 ---------------*/
372  else if( this->layerIndex == 1)
373  {
374    if( event.type == SDLK_RETURN && event.bPressed == true)
375    {
376      this->setNextStoryID( this->menuLayers[1].storyList[this->menuSelectedIndex]->getStoryID());
377      this->stop();
378    }
379    if( event.type == SDLK_ESCAPE && event.bPressed == true)
380    {
381      this->switchMenuLayer(this->layerIndex, 0);
382    }
383  }
384
385
386
387  // The menu selction cursor
388  if( event.type == SDLK_DOWN && event.bPressed == true)
389  {
390    if(this->menuSelectedIndex < (this->menuLayers[this->layerIndex].menuList.size() - 1))
391    {
392      this->menuSelected = this->menuLayers[this->layerIndex].menuList[++this->menuSelectedIndex];
393      this->sliderTo(this->menuSelected, 5.0f);
394      if (this->selectorSource != NULL)
395        this->selectorSource->play();
396
397      if( this->layerIndex == 1)
398      {
399        this->menuLayers[1].screenshootList[this->menuSelectedIndex]->setVisibility(true);
400        this->menuLayers[1].screenshootList[this->menuSelectedIndex-1]->setVisibility(false);
401      }
402    }
403  }
404  else if( event.type == SDLK_UP && event.bPressed == true)
405  {
406    if(this->menuSelectedIndex > 0)
407    {
408      this->menuSelected = this->menuLayers[this->layerIndex].menuList[--this->menuSelectedIndex];
409      this->sliderTo(this->menuSelected, 5.0f);
410      if (this->selectorSource != NULL)
411        this->selectorSource->play();
412
413      if( this->layerIndex == 1)
414      {
415        this->menuLayers[1].screenshootList[this->menuSelectedIndex]->setVisibility(true);
416        this->menuLayers[1].screenshootList[this->menuSelectedIndex+1]->setVisibility(false);
417      }
418    }
419  }
420}
421
422
423/**
424 * @brief switches to from one meny layer to an other
425 * @param layer1 from layer
426 * @param layer2 to layer
427 */
428void SimpleGameMenu::switchMenuLayer(int layer1, int layer2)
429{
430  // wrong sizes
431  if(layer1 >= this->menuLayers.size() || layer2 >= this->menuLayers.size())
432    return;
433
434
435  PRINTF(0)("Removing layer %i\n", layer1);
436  std::vector<TextElement*>::iterator te;
437  // fade old menu
438  for( te = this->menuLayers[layer1].menuList.begin(); te != this->menuLayers[layer1].menuList.end(); te++)
439  {
440    (*te)->setVisibility(false);
441  }
442
443  std::vector<ImageEntity*>::iterator it;
444
445  //also fade the screenshots if in level choosement mode
446  for( it = this->menuLayers[layer1].screenshootList.begin(); it != this->menuLayers[layer1].screenshootList.end(); it++)
447  {
448    (*it)->setVisibility(false);
449  }
450
451
452  PRINTF(0)("Showing layer %i\n", layer1);
453  // beam here the new menu
454  for( te = this->menuLayers[layer2].menuList.begin(); te != this->menuLayers[layer2].menuList.end(); te++ )
455  {
456    (*te)->setVisibility(true);
457  }
458
459
460  this->layerIndex = layer2;
461  this->menuSelected = this->menuLayers[layer2].menuList[0];
462  this->menuSelector->setAbsCoor2D(this->menuSelected->getAbsCoor2D() + Vector2D(0, this->menuSelected->getSizeY2D() *.5));
463  this->menuSelector->setSize2D(this->menuSelected->getSizeX2D()*.7, this->menuSelected->getSizeY2D());
464  this->menuSelectedIndex = 0;
465
466  if( layer2 == 1)
467    this->menuLayers[layer2].screenshootList[0]->setVisibility(true);
468}
469
470void SimpleGameMenu::sliderTo(const Element2D* element, float bias)
471{
472  if (bias > 0.0)
473  {
474    this->menuSelector->setAbsCoorSoft2D(element->getAbsCoor2D() + Vector2D(0, element->getSizeY2D() *.5), bias);
475    this->menuSelector->setSizeSoft2D(element->getSizeX2D()*.7, element->getSizeY2D(), bias);
476  }
477  else
478  {
479    this->menuSelector->setAbsCoor2D(element->getAbsCoor2D() + Vector2D(0, element->getSizeY2D() *.5));
480    this->menuSelector->setSize2D(element->getSizeX2D()*.7, element->getSizeY2D());
481  }
482}
483
484
485
486/**********************************************************************************************
487    SimpleGameMenuData
488 **********************************************************************************************/
489
490
491/**
492 * SimpleGameMenuData constructor
493 */
494SimpleGameMenuData::SimpleGameMenuData()
495{}
496
497/**
498 * SimpleGameMenuData decontructor
499 */
500SimpleGameMenuData::~SimpleGameMenuData()
501{}
502
503
504/**
505 *  initialize the GameWorldDataData
506 */
507ErrorMessage SimpleGameMenuData::init()
508{
509  /* call underlying function */
510  GameWorldData::init();
511}
512
513
514/**
515 *  loads the GUI data
516 * @param root reference to the xml root element
517 */
518ErrorMessage SimpleGameMenuData::loadGUI(const TiXmlElement* root)
519{
520  /* call underlying function */
521  GameWorldData::loadGUI(root);
522}
523
524
525/**
526 *  unloads the GUI data
527 */
528ErrorMessage SimpleGameMenuData::unloadGUI()
529{
530  /* call underlying function */
531  GameWorldData::unloadGUI();
532}
533
534
535/**
536 *  overloads the GameWorld::loadWorldEntities(...) class since the menu WorldEntity loading is different (less loading stuff)
537 * @param root reference to the xml root parameter
538 */
539ErrorMessage SimpleGameMenuData::loadWorldEntities(const TiXmlElement* root)
540{
541  GameWorldData::loadWorldEntities(root);
542  /*
543  const TiXmlElement* element = root->FirstChildElement("WorldEntities");
544
545  if( element != NULL)
546  {
547    element = element->FirstChildElement();
548    PRINTF(4)("Loading WorldEntities\n");
549    while(element != NULL)
550    {
551      BaseObject* created = Factory::fabricate(element);
552      if( created != NULL )
553        printf("Created a %s: %s\n", created->getClassName(), created->getName());
554
555      if( element->Value() == "SkyBox")
556        this->sky = dynamic_cast<WorldEntity*>(created);
557      if( element->Value() == "Terrain")
558        this->terrain = dynamic_cast<Terrain*>(created);
559      element = element->NextSiblingElement();
560    }
561
562    PRINTF(4)("Done loading WorldEntities\n");
563  }
564
565  // init the pnode tree
566  PNode::getNullParent()->init();
567  */
568}
569
570
571/**
572 *  unloads the world entities from the xml file
573 */
574ErrorMessage SimpleGameMenuData::unloadWorldEntities()
575{
576  /* call underlying function */
577  GameWorldData::unloadWorldEntities();
578}
579
580
581/**
582 *  loads the scene data
583 * @param root reference to the xml root element
584 */
585ErrorMessage SimpleGameMenuData::loadScene(const TiXmlElement* root)
586{
587  /* call underlying function */
588  GameWorldData::loadScene(root);
589}
590
591
592/**
593 *  unloads the scene data
594 */
595ErrorMessage SimpleGameMenuData::unloadScene()
596{
597  /* call underlying function */
598  GameWorldData::unloadScene();
599}
600
601
602
Note: See TracBrowser for help on using the repository browser.