Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/main_reto_vs05/src/run_manager.cc @ 288

Last change on this file since 288 was 288, checked in by rgrieder, 16 years ago
  • added Chai's HUD overlay
  • abstracted debugOverlay —> TestOverlay
  • added overlay media files
  • cleaned up RunManager a little bit
  • omitted using ogre's Singleton template
  • added useful CMake structure
  • some more things
File size: 13.8 KB
Line 
1/*
2*   ORXONOX - the hottest 3D action shooter ever to exist
3*
4*
5*   License notice:
6*
7*   This program is free software: you can redistribute it and/or modify
8*   it under the terms of the GNU General Public License as published by
9*   the Free Software Foundation, either version 3 of the License, or
10*   (at your option) any later version.
11*
12*   This program is distributed in the hope that it will be useful,
13*   but WITHOUT ANY WARRANTY; without even the implied warranty of
14*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15*   GNU General Public License for more details.
16*
17*   You should have received a copy of the GNU General Public License
18*   along with this program.  If not, see <http://www.gnu.org/licenses/>.
19*
20*
21*   Author:
22*      Reto Grieder
23*   Co-authors:
24*      ...
25*/
26
27
28#include "OgreVector3.h"
29#include "OgreStringConverter.h"
30#include "OgreRoot.h"
31#include "OgreSceneManager.h"
32#include "OgreSceneNode.h"
33#include "OgreCamera.h"
34#include "OgreViewport.h"
35#include "OgreRenderWindow.h"
36#include "OgreTextureManager.h"
37#include "OgreMaterialManager.h"
38#include "OgreLogManager.h"
39#include "OgreWindowEventUtilities.h"
40
41//Use this define to signify OIS will be used as a DLL
42//(so that dll import/export macros are in effect)
43#define OIS_DYNAMIC_LIB
44#include <OIS/OIS.h>
45
46#include "ogre_control.h"
47#include "orxonox_scene.h"
48#include "orxonox_ship.h"
49#include "inertial_node.h"
50
51#include "weapon/bullet.h"
52#include "weapon/bullet_manager.h"
53#include "weapon/base_weapon.h"
54
55#include "hud/hud_overlay.h"
56#include "hud/test_overlay.h"
57
58#include "run_manager.h"
59
60
61namespace orxonox {
62  using namespace Ogre;
63  using namespace weapon;
64  using namespace hud;
65
66  /**
67  * RunManager is the basic control object during the game.
68  *
69  * The RunManger class is designed to actually "run" the main part of the
70  * game. The Idea is, that you could derive from the RunManager in order
71  * to distinguish between a first person shooter or a space craft shooter.
72  * RunManager loads and initialises everything in the scene (like the ship,
73  * the enemies in the scene, any scripts, the physics, window events,
74  * environment, HUD, etc.).
75  * It also captures any input from keyboard, mous, joystick (optional) or
76  * Ogre (window events).
77  */
78
79
80  RunManager* RunManager::singletonPtr_s = NULL;
81
82
83  /**
84  * Contructor only needs the Root object.
85  */
86  RunManager::RunManager()
87        : ogre_(NULL), window_(NULL), screenShotCounter_(0),
88        timeUntilNextToggle_(0), mouseSensitivity_(0.003), inputManager_(0),
89        mouse_(0), keyboard_(0), joystick_(0), statsOn_(true)
90  {
91  }
92
93  /**
94  * @param ogre_ The OgreControl object holding the render window and the Root
95  */
96  void RunManager::initialise(OgreControl *ogre)
97    {
98    ogre_ = ogre;
99    window_ = ogre->getRenderWindow();
100
101    // SETTING UP THE SCENE
102
103    // create one new SceneManger
104    sceneMgr_ = ogre_->getRoot()->createSceneManager(ST_GENERIC, "Orxonox Scene");
105
106    // background scene (world objects, skybox, lights, etc.)
107    backgroundScene_ = new OrxonoxScene(sceneMgr_);
108
109
110    // BULLET LIST FOR THE TEST APPLICATION
111
112    // create a bullet manager
113    bulletManager_ = new BulletManager(sceneMgr_);
114
115
116    // PLAYER SPACESHIP
117
118    // Create a space ship object and its SceneNode.
119    // It should also be considered, that the ship should provide another Node
120    // for a camera to be attached (otherwise the spaceship in front of the
121    // ship would be very static, never moving at all).
122
123    // Construct a new spaceship and give it the node
124    playerShip_ = new OrxonoxShip(sceneMgr_->getRootSceneNode()
125      ->createChildSceneNode("ShipNode", Vector3(20, 20, 20)));
126
127
128    // RESOURCE LOADING (using ResourceGroups if implemented)
129
130    // load all resources and create the entities by calling the initialise()
131    // methods for each object (no constructor initialisations!).
132    backgroundScene_->initialise();
133    playerShip_->initialise();
134
135
136    // CAMERA AND VIEWPORT
137
138    // create camera and viewport
139    createCamera();
140    createViewports();
141
142    // create HUD
143    hud_ = new hud::TestOverlay(window_);
144    hud_->show();
145
146
147    // Set default mipmap level (NB some APIs ignore this)
148    TextureManager::getSingleton().setDefaultNumMipmaps(5);
149
150
151    // HUMAN INTERFACE
152
153    using namespace OIS;   
154
155    LogManager::getSingletonPtr()->logMessage("*** Initializing OIS ***");
156    ParamList pl;
157    size_t windowHnd = 0;
158    std::ostringstream windowHndStr;
159
160    window_->getCustomAttribute("WINDOW", &windowHnd);
161    windowHndStr << windowHnd;
162    pl.insert(std::make_pair(std::string("WINDOW"), windowHndStr.str()));
163
164    inputManager_ = InputManager::createInputSystem( pl );
165
166    // Create all devices (We only catch joystick exceptions here,
167    // as, most people have Key/Mouse)
168    keyboard_ = static_cast<Keyboard*>(inputManager_
169      ->createInputObject( OISKeyboard, false ));
170    mouse_ = static_cast<Mouse*>(inputManager_
171      ->createInputObject( OISMouse, false ));
172    try {
173      joystick_ = static_cast<JoyStick*>(inputManager_
174        ->createInputObject( OISJoyStick, false ));
175    }
176    catch(...) {
177      joystick_ = 0;
178    }
179
180    //Set initial mouse clipping size
181    windowResized(window_);
182
183    //showDebugOverlay(true);
184
185    // REGISTER THIS OBJECT AS A WINDOW EVENT LISTENER IN OGRE
186    // It will then receive events liek windowClosed, windowResized, etc.
187    WindowEventUtilities::addWindowEventListener(window_, this);
188  }
189
190  /**
191  * Standard destructor.
192  * Removes this object as a window event listener and deletes all created
193  * variables.
194  */
195  RunManager::~RunManager()
196  {
197    //Remove ourself as a Window listener
198    WindowEventUtilities::removeWindowEventListener(window_, this);
199    windowClosed(window_);
200
201    if (backgroundScene_)
202      delete backgroundScene_;
203    if (playerShip_)
204      delete playerShip_;
205    if (bulletManager_)
206      delete bulletManager_;
207    if (hud_)
208      delete hud_;
209  }
210
211
212  /**
213  * Method to compute anything between 2 frames.
214  *
215  * Everything that needs to be computed during the games happens right here.
216  * The only exception are the listeners (which should only set variables,
217  * not actually do something).
218  *
219  * @param time Absolute play time
220  * @param deltaTime Time passed since last frame
221  * @return Return false to end rendering
222  */
223  bool RunManager::tick(unsigned long time, float deltaTime)
224  {
225    // synchronize with internal class timer
226    totalTime_ = time;
227
228    // Call tick() for every object
229    // This could be done by registering (needs a factory..)
230    backgroundScene_->tick(time, deltaTime);
231    playerShip_->tick(time, deltaTime);
232
233
234    // Update the HUD
235    hud_->setDebugText(" | Speed = "
236      + StringConverter::toString(playerShip_->getSpeed())
237      + " | Left Ammo = "
238      + StringConverter::toString(playerShip_
239      ->getMainWeapon()->getAmmoState())
240      + " | Ammo stock = "
241      + StringConverter::toString(playerShip_->getAmmoStock()));
242
243    hud_->tick(time, deltaTime);
244
245    // update the bullet positions
246    bulletManager_->tick(time, deltaTime);
247
248
249    // HUMAN INTERFACE
250
251    using namespace OIS;
252
253    if(window_->isClosed())     return false;
254
255    //Need to capture/update each device
256    keyboard_->capture();
257    mouse_->capture();
258    if( joystick_ ) joystick_->capture();
259
260    bool buffJ = (joystick_) ? joystick_->buffered() : true;
261
262    //Check if one of the devices is not buffered
263    if( !mouse_->buffered() || !keyboard_->buffered() || !buffJ )
264    {
265      // one of the input modes is immediate, so setup what
266      // is needed for immediate movement
267      if (timeUntilNextToggle_ >= 0)
268        timeUntilNextToggle_ -= deltaTime;
269    }
270
271    // handle HID devices
272    if( processUnbufferedKeyInput() == false )
273        return false;
274    if( processUnbufferedMouseInput() == false )
275        return false;
276
277    // keep rendering
278    return true;
279  }
280
281
282  SceneManager& RunManager::getSceneManager()
283  {
284    return *sceneMgr_;
285  }
286
287  SceneManager* RunManager::getSceneManagerPtr()
288  {
289    return sceneMgr_;
290  }
291
292  BulletManager* RunManager::getBulletManagerPtr()
293  {
294    return bulletManager_;
295  }
296
297  int RunManager::getAmmunitionID(const Ogre::String &ammoName)
298  {
299    Ogre::String ammoTypes[] = { "Energy Cell", "Barrel", "Lead Shot" };
300    int ammoTypesLength = 3;
301
302    for (int i = 0; i < ammoTypesLength; i++)
303    {
304      if (ammoTypes[i] == ammoName)
305        return i;
306    }
307    return -1;
308  }
309
310  int RunManager::getNumberOfAmmos()
311  {
312    return 3;
313  }
314
315
316  /**
317  * Adjust mouse clipping area.
318  * This method is called by Ogre without regards of tick()!
319  * Avoid doing too much in this call.
320  * @param rw render window
321  */
322  void RunManager::windowResized(RenderWindow* rw)
323  {
324    unsigned int width, height, depth;
325    int left, top;
326    rw->getMetrics(width, height, depth, left, top);
327
328    const OIS::MouseState &ms = mouse_->getMouseState();
329    ms.width = width;
330    ms.height = height;
331  }
332
333
334  /**
335  * Unattach OIS before window shutdown (very important under Linux).
336  * Again, avoid computing a lot in this function.
337  * @param rw Render Window
338  */
339  void RunManager::windowClosed(RenderWindow* rw)
340  {
341    //Only close for window that created OIS (the main window in these demos)
342    if( rw == window_ )
343    {
344      if( inputManager_ )
345      {
346        inputManager_->destroyInputObject( mouse_ );
347        inputManager_->destroyInputObject( keyboard_ );
348        inputManager_->destroyInputObject( joystick_ );
349
350        OIS::InputManager::destroyInputSystem(inputManager_);
351        inputManager_ = 0;
352      }
353    }
354  }
355
356  /**
357  * Processes the Keyboard input.
358  * TODO: Use listeners to improve performance.
359  * A lookup table should be implemented to bind any key to a specific action.
360  * @return Return true to keep rendering
361  */
362  bool RunManager::processUnbufferedKeyInput()
363  {
364    using namespace OIS;
365
366    if(keyboard_->isKeyDown(KC_A) || keyboard_->isKeyDown(KC_LEFT))
367      playerShip_->setSideThrust(1);
368    else if(keyboard_->isKeyDown(KC_D) || keyboard_->isKeyDown(KC_RIGHT))
369      playerShip_->setSideThrust(-1);
370    else
371      playerShip_->setSideThrust(0);
372
373    if(keyboard_->isKeyDown(KC_UP) || keyboard_->isKeyDown(KC_W) )
374      playerShip_->setMainThrust(1);
375    else if(keyboard_->isKeyDown(KC_DOWN) || keyboard_->isKeyDown(KC_S) )
376      playerShip_->setMainThrust(-1);
377    else
378      playerShip_->setMainThrust(0);
379
380    if (keyboard_->isKeyDown(KC_C))
381      playerShip_->setYThrust(1);
382    else if (keyboard_->isKeyDown(KC_SPACE))
383      playerShip_->setYThrust(-1);
384    else
385      playerShip_->setYThrust(0);
386
387    if (keyboard_->isKeyDown(KC_G))
388      playerShip_->getMainWeapon()->addAction(BaseWeapon::RELOAD);
389
390    if( keyboard_->isKeyDown(KC_ESCAPE) || keyboard_->isKeyDown(KC_Q) )
391      return false;
392
393    if( keyboard_->isKeyDown(KC_F) && timeUntilNextToggle_ <= 0 )
394    {
395      statsOn_ = !statsOn_;
396      timeUntilNextToggle_ = 1;
397    }
398
399    if(keyboard_->isKeyDown(KC_SYSRQ) && timeUntilNextToggle_ <= 0)
400    {
401      std::ostringstream ss;
402      ss << "screenshot_" << ++screenShotCounter_ << ".png";
403      window_->writeContentsToFile(ss.str());
404      timeUntilNextToggle_ = 0.5;
405    }
406
407    // Return true to continue rendering
408    return true;
409  }
410
411
412  /**
413  * Processes the Mouse input.
414  * TODO: Use listeners to improve performance.
415  * A lookup table should be implemented to bind ANY button or movement
416  * to a specific action.
417  * @return Return true to keep rendering
418  */
419  bool RunManager::processUnbufferedMouseInput()
420  {
421    using namespace OIS;
422
423    const MouseState &ms = mouse_->getMouseState();
424
425    if (ms.buttonDown(MB_Left))
426      playerShip_->getMainWeapon()->primaryFireRequest();
427
428    if (ms.buttonDown(MB_Right))
429      playerShip_->getMainWeapon()->secondaryFireRequest();
430
431    playerShip_->turnUpAndDown(Radian(ms.Y.rel * mouseSensitivity_));
432    playerShip_->turnLeftAndRight(Radian(ms.X.rel * mouseSensitivity_));
433
434    // keep rendering
435    return true;
436  }
437
438  /**
439  * Show an overlay desired.
440  * @param show Whether or not to show the debug overlay
441  */
442  void RunManager::showDebugOverlay(bool show)
443  {
444    if (hud_)
445    {
446      if (show)
447        hud_->show();
448      else
449        hud_->hide();
450    }
451  }
452
453
454  /**
455  * Simple camera creator.
456  * playerShip_Node->attachObject(camera_) should not be here! This is what
457  * the camera manager is for. Right now, this method should do just fine,
458  * setting the cam behind the ship.
459  */
460  void RunManager::createCamera()
461  {
462    camera_ = sceneMgr_->createCamera("PlayerCam");
463    playerShip_->getRootNode()->getSceneNode()->attachObject(camera_);
464    camera_->setNearClipDistance(5);
465    camera_->setPosition(Vector3(0,10,500));
466    camera_->lookAt(Vector3(0,0,0));
467  }
468
469  /**
470  * Simple viewport creator.
471  * For now the viewport uses the entire render window and is based on the one
472  * camera created so far.
473  */
474  void RunManager::createViewports()
475  {
476    // Create one viewport, entire window
477    Viewport* vp = window_->addViewport(camera_);
478    vp->setBackgroundColour(ColourValue(0,0,0));
479
480    // Alter the camera aspect ratio to match the viewport
481    camera_->setAspectRatio(
482      Real(vp->getActualWidth()) / Real(vp->getActualHeight()));
483  }
484
485
486  RunManager* RunManager::createSingleton()
487  {
488    if (singletonPtr_s)
489      return NULL;
490    singletonPtr_s = new RunManager();
491    return singletonPtr_s;
492  }
493
494  void RunManager::destroySingleton()
495  {
496    if (singletonPtr_s)
497      delete singletonPtr_s;
498  }
499
500
501  RunManager& RunManager::getSingleton()
502  {
503    return *singletonPtr_s;
504  }
505
506  RunManager* RunManager::getSingletonPtr()
507  {
508    return singletonPtr_s;
509  }
510
511}
Note: See TracBrowser for help on using the repository browser.