Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 307 was 291, checked in by rgrieder, 17 years ago
  • fixed a minor bug with string —> string& conversion (illegal with gcc)
File size: 13.9 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
[291]235    Ogre::String tempStr = " | Speed = "
[288]236      + StringConverter::toString(playerShip_->getSpeed())
237      + " | Left Ammo = "
238      + StringConverter::toString(playerShip_
239      ->getMainWeapon()->getAmmoState())
240      + " | Ammo stock = "
[291]241      + StringConverter::toString(playerShip_->getAmmoStock());
242    hud_->setDebugText(tempStr);
[157]243
[288]244    hud_->tick(time, deltaTime);
245
[161]246    // update the bullet positions
[177]247    bulletManager_->tick(time, deltaTime);
248
[157]249
[161]250    // HUMAN INTERFACE
[157]251
[161]252    using namespace OIS;
[157]253
[161]254    if(window_->isClosed())     return false;
[157]255
[161]256    //Need to capture/update each device
257    keyboard_->capture();
258    mouse_->capture();
259    if( joystick_ ) joystick_->capture();
[157]260
[161]261    bool buffJ = (joystick_) ? joystick_->buffered() : true;
[157]262
[161]263    //Check if one of the devices is not buffered
264    if( !mouse_->buffered() || !keyboard_->buffered() || !buffJ )
265    {
266      // one of the input modes is immediate, so setup what
267      // is needed for immediate movement
268      if (timeUntilNextToggle_ >= 0)
269        timeUntilNextToggle_ -= deltaTime;
270    }
[157]271
[161]272    // handle HID devices
273    if( processUnbufferedKeyInput() == false )
274        return false;
275    if( processUnbufferedMouseInput() == false )
276        return false;
[157]277
[161]278    // keep rendering
279    return true;
280  }
[157]281
282
[232]283  SceneManager& RunManager::getSceneManager()
284  {
285    return *sceneMgr_;
286  }
287
288  SceneManager* RunManager::getSceneManagerPtr()
289  {
290    return sceneMgr_;
291  }
292
293  BulletManager* RunManager::getBulletManagerPtr()
294  {
295    return bulletManager_;
296  }
297
298  int RunManager::getAmmunitionID(const Ogre::String &ammoName)
299  {
300    Ogre::String ammoTypes[] = { "Energy Cell", "Barrel", "Lead Shot" };
301    int ammoTypesLength = 3;
302
303    for (int i = 0; i < ammoTypesLength; i++)
304    {
305      if (ammoTypes[i] == ammoName)
306        return i;
307    }
308    return -1;
309  }
310
311  int RunManager::getNumberOfAmmos()
312  {
313    return 3;
314  }
315
316
[161]317  /**
318  * Adjust mouse clipping area.
319  * This method is called by Ogre without regards of tick()!
320  * Avoid doing too much in this call.
321  * @param rw render window
322  */
323  void RunManager::windowResized(RenderWindow* rw)
324  {
325    unsigned int width, height, depth;
326    int left, top;
327    rw->getMetrics(width, height, depth, left, top);
[157]328
[161]329    const OIS::MouseState &ms = mouse_->getMouseState();
330    ms.width = width;
331    ms.height = height;
332  }
[157]333
334
[161]335  /**
336  * Unattach OIS before window shutdown (very important under Linux).
337  * Again, avoid computing a lot in this function.
338  * @param rw Render Window
339  */
340  void RunManager::windowClosed(RenderWindow* rw)
[157]341  {
[161]342    //Only close for window that created OIS (the main window in these demos)
343    if( rw == window_ )
[157]344    {
[161]345      if( inputManager_ )
346      {
347        inputManager_->destroyInputObject( mouse_ );
348        inputManager_->destroyInputObject( keyboard_ );
349        inputManager_->destroyInputObject( joystick_ );
[157]350
[161]351        OIS::InputManager::destroyInputSystem(inputManager_);
352        inputManager_ = 0;
353      }
[157]354    }
355  }
356
[161]357  /**
358  * Processes the Keyboard input.
359  * TODO: Use listeners to improve performance.
360  * A lookup table should be implemented to bind any key to a specific action.
361  * @return Return true to keep rendering
362  */
363  bool RunManager::processUnbufferedKeyInput()
364  {
365    using namespace OIS;
[157]366
[161]367    if(keyboard_->isKeyDown(KC_A) || keyboard_->isKeyDown(KC_LEFT))
368      playerShip_->setSideThrust(1);
369    else if(keyboard_->isKeyDown(KC_D) || keyboard_->isKeyDown(KC_RIGHT))
370      playerShip_->setSideThrust(-1);
371    else
372      playerShip_->setSideThrust(0);
[157]373
[161]374    if(keyboard_->isKeyDown(KC_UP) || keyboard_->isKeyDown(KC_W) )
375      playerShip_->setMainThrust(1);
376    else if(keyboard_->isKeyDown(KC_DOWN) || keyboard_->isKeyDown(KC_S) )
377      playerShip_->setMainThrust(-1);
378    else
379      playerShip_->setMainThrust(0);
[157]380
[161]381    if (keyboard_->isKeyDown(KC_C))
382      playerShip_->setYThrust(1);
383    else if (keyboard_->isKeyDown(KC_SPACE))
384      playerShip_->setYThrust(-1);
385    else
386      playerShip_->setYThrust(0);
[159]387
[194]388    if (keyboard_->isKeyDown(KC_G))
[198]389      playerShip_->getMainWeapon()->addAction(BaseWeapon::RELOAD);
[194]390
[161]391    if( keyboard_->isKeyDown(KC_ESCAPE) || keyboard_->isKeyDown(KC_Q) )
392      return false;
[157]393
[161]394    if( keyboard_->isKeyDown(KC_F) && timeUntilNextToggle_ <= 0 )
395    {
396      statsOn_ = !statsOn_;
397      timeUntilNextToggle_ = 1;
398    }
[157]399
[161]400    if(keyboard_->isKeyDown(KC_SYSRQ) && timeUntilNextToggle_ <= 0)
401    {
402      std::ostringstream ss;
403      ss << "screenshot_" << ++screenShotCounter_ << ".png";
404      window_->writeContentsToFile(ss.str());
405      timeUntilNextToggle_ = 0.5;
406    }
[157]407
[161]408    // Return true to continue rendering
409    return true;
[157]410  }
411
412
[161]413  /**
414  * Processes the Mouse input.
415  * TODO: Use listeners to improve performance.
416  * A lookup table should be implemented to bind ANY button or movement
417  * to a specific action.
418  * @return Return true to keep rendering
419  */
420  bool RunManager::processUnbufferedMouseInput()
421  {
422    using namespace OIS;
[157]423
[161]424    const MouseState &ms = mouse_->getMouseState();
[157]425
[194]426    if (ms.buttonDown(MB_Left))
427      playerShip_->getMainWeapon()->primaryFireRequest();
[177]428
[194]429    if (ms.buttonDown(MB_Right))
430      playerShip_->getMainWeapon()->secondaryFireRequest();
[157]431
[161]432    playerShip_->turnUpAndDown(Radian(ms.Y.rel * mouseSensitivity_));
433    playerShip_->turnLeftAndRight(Radian(ms.X.rel * mouseSensitivity_));
[157]434
[161]435    // keep rendering
436    return true;
[157]437  }
438
[161]439  /**
[288]440  * Show an overlay desired.
[161]441  * @param show Whether or not to show the debug overlay
442  */
443  void RunManager::showDebugOverlay(bool show)
[157]444  {
[288]445    if (hud_)
[161]446    {
447      if (show)
[288]448        hud_->show();
[161]449      else
[288]450        hud_->hide();
[161]451    }
[157]452  }
453
454
[161]455  /**
456  * Simple camera creator.
[288]457  * playerShip_Node->attachObject(camera_) should not be here! This is what
458  * the camera manager is for. Right now, this method should do just fine,
459  * setting the cam behind the ship.
[161]460  */
[288]461  void RunManager::createCamera()
[161]462  {
463    camera_ = sceneMgr_->createCamera("PlayerCam");
[189]464    playerShip_->getRootNode()->getSceneNode()->attachObject(camera_);
[161]465    camera_->setNearClipDistance(5);
466    camera_->setPosition(Vector3(0,10,500));
467    camera_->lookAt(Vector3(0,0,0));
468  }
[157]469
[161]470  /**
471  * Simple viewport creator.
472  * For now the viewport uses the entire render window and is based on the one
473  * camera created so far.
474  */
[288]475  void RunManager::createViewports()
[161]476  {
477    // Create one viewport, entire window
478    Viewport* vp = window_->addViewport(camera_);
479    vp->setBackgroundColour(ColourValue(0,0,0));
[157]480
[161]481    // Alter the camera aspect ratio to match the viewport
482    camera_->setAspectRatio(
483      Real(vp->getActualWidth()) / Real(vp->getActualHeight()));
484  }
485
[288]486
487  RunManager* RunManager::createSingleton()
488  {
489    if (singletonPtr_s)
490      return NULL;
491    singletonPtr_s = new RunManager();
492    return singletonPtr_s;
493  }
494
495  void RunManager::destroySingleton()
496  {
497    if (singletonPtr_s)
498      delete singletonPtr_s;
499  }
500
501
502  RunManager& RunManager::getSingleton()
503  {
504    return *singletonPtr_s;
505  }
506
507  RunManager* RunManager::getSingletonPtr()
508  {
509    return singletonPtr_s;
510  }
511
[291]512}
Note: See TracBrowser for help on using the repository browser.