Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 289 was 288, checked in by rgrieder, 17 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
RevLine 
[157]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
[160]27
[288]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"
[161]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"
[189]49#include "inertial_node.h"
[161]50
[193]51#include "weapon/bullet.h"
52#include "weapon/bullet_manager.h"
[198]53#include "weapon/base_weapon.h"
[193]54
[288]55#include "hud/hud_overlay.h"
56#include "hud/test_overlay.h"
57
[157]58#include "run_manager.h"
59
[232]60
[169]61namespace orxonox {
[161]62  using namespace Ogre;
[189]63  using namespace weapon;
[288]64  using namespace hud;
[157]65
[161]66  /**
[169]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
[288]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)
[232]90  {
91  }
[169]92
93  /**
[161]94  * @param ogre_ The OgreControl object holding the render window and the Root
95  */
[288]96  void RunManager::initialise(OgreControl *ogre)
97    {
98    ogre_ = ogre;
99    window_ = ogre->getRenderWindow();
100
[161]101    // SETTING UP THE SCENE
[157]102
[161]103    // create one new SceneManger
[232]104    sceneMgr_ = ogre_->getRoot()->createSceneManager(ST_GENERIC, "Orxonox Scene");
[157]105
[161]106    // background scene (world objects, skybox, lights, etc.)
107    backgroundScene_ = new OrxonoxScene(sceneMgr_);
[157]108
[177]109
110    // BULLET LIST FOR THE TEST APPLICATION
111
112    // create a bullet manager
113    bulletManager_ = new BulletManager(sceneMgr_);
114
115
[161]116    // PLAYER SPACESHIP
[157]117
[161]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
[288]121    // ship would be very static, never moving at all).
[157]122
[161]123    // Construct a new spaceship and give it the node
[232]124    playerShip_ = new OrxonoxShip(sceneMgr_->getRootSceneNode()
125      ->createChildSceneNode("ShipNode", Vector3(20, 20, 20)));
[157]126
127
[161]128    // RESOURCE LOADING (using ResourceGroups if implemented)
[157]129
[161]130    // load all resources and create the entities by calling the initialise()
[288]131    // methods for each object (no constructor initialisations!).
[161]132    backgroundScene_->initialise();
133    playerShip_->initialise();
[157]134
135
[161]136    // CAMERA AND VIEWPORT
[157]137
[161]138    // create camera and viewport
139    createCamera();
140    createViewports();
[157]141
[288]142    // create HUD
143    hud_ = new hud::TestOverlay(window_);
144    hud_->show();
[157]145
[288]146
[161]147    // Set default mipmap level (NB some APIs ignore this)
148    TextureManager::getSingleton().setDefaultNumMipmaps(5);
[157]149
150
[161]151    // HUMAN INTERFACE
[157]152
[288]153    using namespace OIS;   
[157]154
[161]155    LogManager::getSingletonPtr()->logMessage("*** Initializing OIS ***");
156    ParamList pl;
157    size_t windowHnd = 0;
158    std::ostringstream windowHndStr;
[157]159
[161]160    window_->getCustomAttribute("WINDOW", &windowHnd);
161    windowHndStr << windowHnd;
162    pl.insert(std::make_pair(std::string("WINDOW"), windowHndStr.str()));
[157]163
[161]164    inputManager_ = InputManager::createInputSystem( pl );
[157]165
[161]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    }
[157]179
[161]180    //Set initial mouse clipping size
181    windowResized(window_);
[157]182
[288]183    //showDebugOverlay(true);
[157]184
[161]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  }
[157]189
[161]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_);
[157]200
[161]201    if (backgroundScene_)
202      delete backgroundScene_;
203    if (playerShip_)
204      delete playerShip_;
[177]205    if (bulletManager_)
206      delete bulletManager_;
[288]207    if (hud_)
208      delete hud_;
[161]209  }
[157]210
211
[161]212  /**
[288]213  * Method to compute anything between 2 frames.
[161]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;
[157]227
[161]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);
[157]232
233
[288]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()));
[157]242
[288]243    hud_->tick(time, deltaTime);
244
[161]245    // update the bullet positions
[177]246    bulletManager_->tick(time, deltaTime);
247
[157]248
[161]249    // HUMAN INTERFACE
[157]250
[161]251    using namespace OIS;
[157]252
[161]253    if(window_->isClosed())     return false;
[157]254
[161]255    //Need to capture/update each device
256    keyboard_->capture();
257    mouse_->capture();
258    if( joystick_ ) joystick_->capture();
[157]259
[161]260    bool buffJ = (joystick_) ? joystick_->buffered() : true;
[157]261
[161]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    }
[157]270
[161]271    // handle HID devices
272    if( processUnbufferedKeyInput() == false )
273        return false;
274    if( processUnbufferedMouseInput() == false )
275        return false;
[157]276
[161]277    // keep rendering
278    return true;
279  }
[157]280
281
[232]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
[161]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);
[157]327
[161]328    const OIS::MouseState &ms = mouse_->getMouseState();
329    ms.width = width;
330    ms.height = height;
331  }
[157]332
333
[161]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)
[157]340  {
[161]341    //Only close for window that created OIS (the main window in these demos)
342    if( rw == window_ )
[157]343    {
[161]344      if( inputManager_ )
345      {
346        inputManager_->destroyInputObject( mouse_ );
347        inputManager_->destroyInputObject( keyboard_ );
348        inputManager_->destroyInputObject( joystick_ );
[157]349
[161]350        OIS::InputManager::destroyInputSystem(inputManager_);
351        inputManager_ = 0;
352      }
[157]353    }
354  }
355
[161]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;
[157]365
[161]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);
[157]372
[161]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);
[157]379
[161]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);
[159]386
[194]387    if (keyboard_->isKeyDown(KC_G))
[198]388      playerShip_->getMainWeapon()->addAction(BaseWeapon::RELOAD);
[194]389
[161]390    if( keyboard_->isKeyDown(KC_ESCAPE) || keyboard_->isKeyDown(KC_Q) )
391      return false;
[157]392
[161]393    if( keyboard_->isKeyDown(KC_F) && timeUntilNextToggle_ <= 0 )
394    {
395      statsOn_ = !statsOn_;
396      timeUntilNextToggle_ = 1;
397    }
[157]398
[161]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    }
[157]406
[161]407    // Return true to continue rendering
408    return true;
[157]409  }
410
411
[161]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;
[157]422
[161]423    const MouseState &ms = mouse_->getMouseState();
[157]424
[194]425    if (ms.buttonDown(MB_Left))
426      playerShip_->getMainWeapon()->primaryFireRequest();
[177]427
[194]428    if (ms.buttonDown(MB_Right))
429      playerShip_->getMainWeapon()->secondaryFireRequest();
[157]430
[161]431    playerShip_->turnUpAndDown(Radian(ms.Y.rel * mouseSensitivity_));
432    playerShip_->turnLeftAndRight(Radian(ms.X.rel * mouseSensitivity_));
[157]433
[161]434    // keep rendering
435    return true;
[157]436  }
437
[161]438  /**
[288]439  * Show an overlay desired.
[161]440  * @param show Whether or not to show the debug overlay
441  */
442  void RunManager::showDebugOverlay(bool show)
[157]443  {
[288]444    if (hud_)
[161]445    {
446      if (show)
[288]447        hud_->show();
[161]448      else
[288]449        hud_->hide();
[161]450    }
[157]451  }
452
453
[161]454  /**
455  * Simple camera creator.
[288]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.
[161]459  */
[288]460  void RunManager::createCamera()
[161]461  {
462    camera_ = sceneMgr_->createCamera("PlayerCam");
[189]463    playerShip_->getRootNode()->getSceneNode()->attachObject(camera_);
[161]464    camera_->setNearClipDistance(5);
465    camera_->setPosition(Vector3(0,10,500));
466    camera_->lookAt(Vector3(0,0,0));
467  }
[157]468
[161]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  */
[288]474  void RunManager::createViewports()
[161]475  {
476    // Create one viewport, entire window
477    Viewport* vp = window_->addViewport(camera_);
478    vp->setBackgroundColour(ColourValue(0,0,0));
[157]479
[161]480    // Alter the camera aspect ratio to match the viewport
481    camera_->setAspectRatio(
482      Real(vp->getActualWidth()) / Real(vp->getActualHeight()));
483  }
484
[288]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.