Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/merger/src/run_manager.cc @ 322

Last change on this file since 322 was 300, checked in by nicolasc, 17 years ago

initial merge of main_reto

File size: 13.9 KB
RevLine 
[171]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
[289]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"
[171]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"
[190]49#include "inertial_node.h"
[171]50
[192]51#include "weapon/bullet.h"
52#include "weapon/bullet_manager.h"
[267]53#include "weapon/base_weapon.h"
[192]54
[267]55#include "hud/hud_overlay.h"
[289]56#include "hud/test_overlay.h"
[267]57
[171]58#include "run_manager.h"
59
[267]60
[171]61namespace orxonox {
62  using namespace Ogre;
[190]63  using namespace weapon;
[267]64  using namespace hud;
[171]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
[289]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)
[267]90  {
91  }
[171]92
93  /**
94  * @param ogre_ The OgreControl object holding the render window and the Root
95  */
[289]96  void RunManager::initialise(OgreControl *ogre)
97    {
98    ogre_ = ogre;
99    window_ = ogre->getRenderWindow();
100
[171]101    // SETTING UP THE SCENE
102
103    // create one new SceneManger
[267]104    sceneMgr_ = ogre_->getRoot()->createSceneManager(ST_GENERIC, "Orxonox Scene");
[171]105
106    // background scene (world objects, skybox, lights, etc.)
107    backgroundScene_ = new OrxonoxScene(sceneMgr_);
108
[190]109
110    // BULLET LIST FOR THE TEST APPLICATION
111
112    // create a bullet manager
113    bulletManager_ = new BulletManager(sceneMgr_);
114
115
[171]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
[289]121    // ship would be very static, never moving at all).
[171]122
123    // Construct a new spaceship and give it the node
[267]124    playerShip_ = new OrxonoxShip(sceneMgr_->getRootSceneNode()
125      ->createChildSceneNode("ShipNode", Vector3(20, 20, 20)));
[171]126
127
128    // RESOURCE LOADING (using ResourceGroups if implemented)
129
130    // load all resources and create the entities by calling the initialise()
[289]131    // methods for each object (no constructor initialisations!).
[171]132    backgroundScene_->initialise();
133    playerShip_->initialise();
134
135
136    // CAMERA AND VIEWPORT
137
138    // create camera and viewport
139    createCamera();
140    createViewports();
141
[267]142    // create HUD
[289]143    hud_ = new hud::TestOverlay(window_);
[267]144    hud_->show();
[171]145
[267]146
[171]147    // Set default mipmap level (NB some APIs ignore this)
148    TextureManager::getSingleton().setDefaultNumMipmaps(5);
149
150
151    // HUMAN INTERFACE
152
[289]153    using namespace OIS;   
[171]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
[267]183    //showDebugOverlay(true);
[171]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_;
[190]205    if (bulletManager_)
206      delete bulletManager_;
[289]207    if (hud_)
208      delete hud_;
[171]209  }
210
211
212  /**
[289]213  * Method to compute anything between 2 frames.
[171]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
[289]234    // Update the HUD
[292]235    Ogre::String tempStr = " | Speed = "
[289]236      + StringConverter::toString(playerShip_->getSpeed())
237      + " | Left Ammo = "
238      + StringConverter::toString(playerShip_
239      ->getMainWeapon()->getAmmoState())
240      + " | Ammo stock = "
[292]241      + StringConverter::toString(playerShip_->getAmmoStock());
242    hud_->setDebugText(tempStr);
[171]243
[289]244    hud_->tick(time, deltaTime);
245
[171]246    // update the bullet positions
[190]247    bulletManager_->tick(time, deltaTime);
248
[171]249
250    // HUMAN INTERFACE
251
252    using namespace OIS;
253
254    if(window_->isClosed())     return false;
255
256    //Need to capture/update each device
257    keyboard_->capture();
258    mouse_->capture();
259    if( joystick_ ) joystick_->capture();
260
261    bool buffJ = (joystick_) ? joystick_->buffered() : true;
262
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    }
271
272    // handle HID devices
273    if( processUnbufferedKeyInput() == false )
274        return false;
275    if( processUnbufferedMouseInput() == false )
276        return false;
277
278    // keep rendering
279    return true;
280  }
281
282
[267]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
[171]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);
328
329    const OIS::MouseState &ms = mouse_->getMouseState();
330    ms.width = width;
331    ms.height = height;
332  }
333
334
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)
341  {
342    //Only close for window that created OIS (the main window in these demos)
343    if( rw == window_ )
344    {
345      if( inputManager_ )
346      {
347        inputManager_->destroyInputObject( mouse_ );
348        inputManager_->destroyInputObject( keyboard_ );
349        inputManager_->destroyInputObject( joystick_ );
350
351        OIS::InputManager::destroyInputSystem(inputManager_);
352        inputManager_ = 0;
353      }
354    }
355  }
356
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;
366
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);
373
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);
380
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);
387
[267]388    if (keyboard_->isKeyDown(KC_G))
389      playerShip_->getMainWeapon()->addAction(BaseWeapon::RELOAD);
390
[171]391    if( keyboard_->isKeyDown(KC_ESCAPE) || keyboard_->isKeyDown(KC_Q) )
392      return false;
393
394    if( keyboard_->isKeyDown(KC_F) && timeUntilNextToggle_ <= 0 )
395    {
396      statsOn_ = !statsOn_;
397      timeUntilNextToggle_ = 1;
398    }
399
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    }
407
408    // Return true to continue rendering
409    return true;
410  }
411
412
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;
423
424    const MouseState &ms = mouse_->getMouseState();
425
[267]426    if (ms.buttonDown(MB_Left))
427      playerShip_->getMainWeapon()->primaryFireRequest();
[190]428
[267]429    if (ms.buttonDown(MB_Right))
430      playerShip_->getMainWeapon()->secondaryFireRequest();
[171]431
432    playerShip_->turnUpAndDown(Radian(ms.Y.rel * mouseSensitivity_));
433    playerShip_->turnLeftAndRight(Radian(ms.X.rel * mouseSensitivity_));
434
435    // keep rendering
436    return true;
437  }
438
439  /**
[289]440  * Show an overlay desired.
[171]441  * @param show Whether or not to show the debug overlay
442  */
443  void RunManager::showDebugOverlay(bool show)
444  {
[289]445    if (hud_)
[171]446    {
447      if (show)
[289]448        hud_->show();
[171]449      else
[289]450        hud_->hide();
[171]451    }
452  }
453
454
455  /**
456  * Simple camera creator.
[289]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.
[171]460  */
[289]461  void RunManager::createCamera()
[171]462  {
463    camera_ = sceneMgr_->createCamera("PlayerCam");
[190]464    playerShip_->getRootNode()->getSceneNode()->attachObject(camera_);
[171]465    camera_->setNearClipDistance(5);
466    camera_->setPosition(Vector3(0,10,500));
467    camera_->lookAt(Vector3(0,0,0));
468  }
469
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  */
[289]475  void RunManager::createViewports()
[171]476  {
477    // Create one viewport, entire window
478    Viewport* vp = window_->addViewport(camera_);
479    vp->setBackgroundColour(ColourValue(0,0,0));
480
481    // Alter the camera aspect ratio to match the viewport
482    camera_->setAspectRatio(
483      Real(vp->getActualWidth()) / Real(vp->getActualHeight()));
484  }
485
[289]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
[292]512}
Note: See TracBrowser for help on using the repository browser.