Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/main_reto/src/run_manager.cc @ 267

Last change on this file since 267 was 267, checked in by rgrieder, 16 years ago
  • updated to current revision from Visual studio directory
  • hopefully working libraries with cmake
File size: 18.6 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 "Ogre.h"
29//#include "OgreRoot.h"
30//#include "OgreSceneManager.h"
31//#include "OgreSceneNode.h"
32//#include "OgreCamera.h"
33//#include "OgreViewport.h"
34//#include "OgreRenderWindow.h"
35//#include "OgreOverlay.h"
36//#include "OgreOverlayManager.h"
37//#include "OgreOverlayElement.h"
38//#include "OgreTextureManager.h"
39//#include "OgreMaterialManager.h"
40//#include "OgreLogManager.h"
41//#include "OgreVector3.h"
42//#include "OgreStringConverter.h"
43//#include "OgreWindowEventUtilities.h"
44
45//Use this define to signify OIS will be used as a DLL
46//(so that dll import/export macros are in effect)
47#define OIS_DYNAMIC_LIB
48#include <OIS/OIS.h>
49
50#include "ogre_control.h"
51#include "orxonox_scene.h"
52#include "orxonox_ship.h"
53#include "camera_manager.h"
54#include "inertial_node.h"
55
56#include "weapon/bullet.h"
57#include "weapon/bullet_manager.h"
58#include "weapon/base_weapon.h"
59
60#include "hud/hud_overlay.h"
61
62#include "run_manager.h"
63
64namespace Ogre {
65  using namespace orxonox;
66  template<> RunManager* Singleton<RunManager>::ms_Singleton = 0;
67}
68
69namespace orxonox {
70  using namespace Ogre;
71  using namespace weapon;
72  using namespace hud;
73
74  /**
75  * RunManager is the basic control object during the game.
76  *
77  * The RunManger class is designed to actually "run" the main part of the
78  * game. The Idea is, that you could derive from the RunManager in order
79  * to distinguish between a first person shooter or a space craft shooter.
80  * RunManager loads and initialises everything in the scene (like the ship,
81  * the enemies in the scene, any scripts, the physics, window events,
82  * environment, HUD, etc.).
83  * It also captures any input from keyboard, mous, joystick (optional) or
84  * Ogre (window events).
85  */
86
87  RunManager* RunManager::getSingletonPtr(void)
88  {
89      return ms_Singleton;
90  }
91  RunManager& RunManager::getSingleton(void)
92  { 
93      assert( ms_Singleton );  return ( *ms_Singleton ); 
94  }
95
96
97  /**
98  * Contructor only needs the render window and the Root object which are both
99  * the OgreControl object.
100  * Right now the constructor does all the initialisation work. This could also
101  * be done in a new method "initialize()", for whatever purpose.
102  *
103  *
104  * @param ogre_ The OgreControl object holding the render window and the Root
105  */
106  RunManager::RunManager(OgreControl * ogre)
107        : ogre_(ogre), window_(ogre->getRenderWindow()), //leftButtonDown_(false),
108        statsOn_(true), screenShotCounter_(0), timeUntilNextToggle_(0),
109        filtering_(TFO_BILINEAR), aniso_(1), sceneDetailIndex_(0),
110        mouseSensitivity_(0.003),
111        debugOverlay_(0), inputManager_(0), mouse_(0), keyboard_(0), joystick_(0)
112  {
113    // SETTING UP THE SCENE
114
115    // create one new SceneManger
116    sceneMgr_ = ogre_->getRoot()->createSceneManager(ST_GENERIC, "Orxonox Scene");
117
118    // background scene (world objects, skybox, lights, etc.)
119    backgroundScene_ = new OrxonoxScene(sceneMgr_);
120
121
122    // BULLET LIST FOR THE TEST APPLICATION
123
124    // create a bullet manager
125    bulletManager_ = new BulletManager(sceneMgr_);
126
127
128    // PLAYER SPACESHIP
129
130    // Create a space ship object and its SceneNode.
131    // Some ideas about the steering: The ship should only receive events like
132    // up, down, left, right, roll left, roll right, move down, move up, etc).
133    // Multiple interpretations of these commands would make the game more
134    // but it also makes AI steering more difficult, since for every type of
135    // steering, new methods have to be written.
136    // --> clearly define how a space ship can fly (rolling?, conservation of
137    // impuls?, direct mouse sight steeering?, etc.)
138    // It should also be considered, that the ship should provide another Node
139    // for a camera to be attached (otherwise the spaceship in front of the
140    // would be very static, never moving at all).
141
142    // Construct a new spaceship and give it the node
143    playerShip_ = new OrxonoxShip(sceneMgr_->getRootSceneNode()
144      ->createChildSceneNode("ShipNode", Vector3(20, 20, 20)));
145
146
147    // RESOURCE LOADING (using ResourceGroups if implemented)
148
149    // load all resources and create the entities by calling the initialise()
150    // methods for each object (don't initialise in the constructor!).
151    backgroundScene_->initialise();
152    playerShip_->initialise();
153
154
155    // CAMERA AND VIEWPORT
156    // TODO: create a camera manager. It should be able to change its position
157    // around the space ship (predefined states would be nice too). And it should
158    // also be able to switch between different locations (like ship, spactator,
159    // certain fixed positions (e.g. finish line, etc.)). These are just ideas.
160
161    // create camera and viewport
162    createCamera();
163    createViewports();
164
165    // create HUD
166    hud_ = new HUDOverlay();
167    hud_->show();
168
169
170    // Set default mipmap level (NB some APIs ignore this)
171    TextureManager::getSingleton().setDefaultNumMipmaps(5);
172
173   
174
175    // HUMAN INTERFACE
176
177    using namespace OIS;
178
179    //debugOverlay_ = OverlayManager::getSingleton()
180    //  .getByName("Core/DebugOverlay");
181   
182
183    LogManager::getSingletonPtr()->logMessage("*** Initializing OIS ***");
184    ParamList pl;
185    size_t windowHnd = 0;
186    std::ostringstream windowHndStr;
187
188    window_->getCustomAttribute("WINDOW", &windowHnd);
189    windowHndStr << windowHnd;
190    pl.insert(std::make_pair(std::string("WINDOW"), windowHndStr.str()));
191
192    inputManager_ = InputManager::createInputSystem( pl );
193
194    // Create all devices (We only catch joystick exceptions here,
195    // as, most people have Key/Mouse)
196    keyboard_ = static_cast<Keyboard*>(inputManager_
197      ->createInputObject( OISKeyboard, false ));
198    mouse_ = static_cast<Mouse*>(inputManager_
199      ->createInputObject( OISMouse, false ));
200    try {
201      joystick_ = static_cast<JoyStick*>(inputManager_
202        ->createInputObject( OISJoyStick, false ));
203    }
204    catch(...) {
205      joystick_ = 0;
206    }
207
208    //Set initial mouse clipping size
209    windowResized(window_);
210
211    //showDebugOverlay(true);
212
213    // REGISTER THIS OBJECT AS A WINDOW EVENT LISTENER IN OGRE
214    // It will then receive events liek windowClosed, windowResized, etc.
215    WindowEventUtilities::addWindowEventListener(window_, this);
216  }
217
218  /**
219  * Standard destructor.
220  * Removes this object as a window event listener and deletes all created
221  * variables.
222  */
223  RunManager::~RunManager()
224  {
225    //Remove ourself as a Window listener
226    WindowEventUtilities::removeWindowEventListener(window_, this);
227    windowClosed(window_);
228
229    if (backgroundScene_)
230      delete backgroundScene_;
231    if (playerShip_)
232      delete playerShip_;
233    if (bulletManager_)
234      delete bulletManager_;
235  }
236
237
238  /**
239  * Method to compute anyting between 2 frames.
240  *
241  * Everything that needs to be computed during the games happens right here.
242  * The only exception are the listeners (which should only set variables,
243  * not actually do something).
244  *
245  * @param time Absolute play time
246  * @param deltaTime Time passed since last frame
247  * @return Return false to end rendering
248  */
249  bool RunManager::tick(unsigned long time, float deltaTime)
250  {
251    // synchronize with internal class timer
252    totalTime_ = time;
253
254    // Call tick() for every object
255    // This could be done by registering (needs a factory..)
256    backgroundScene_->tick(time, deltaTime);
257    playerShip_->tick(time, deltaTime);
258
259
260    // Update the 'HUD'
261    //updateStats();
262
263    // update the bullet positions
264    bulletManager_->tick(time, deltaTime);
265
266
267    // HUMAN INTERFACE
268
269    using namespace OIS;
270
271    if(window_->isClosed())     return false;
272
273    //Need to capture/update each device
274    keyboard_->capture();
275    mouse_->capture();
276    if( joystick_ ) joystick_->capture();
277
278    bool buffJ = (joystick_) ? joystick_->buffered() : true;
279
280    //Check if one of the devices is not buffered
281    if( !mouse_->buffered() || !keyboard_->buffered() || !buffJ )
282    {
283      // one of the input modes is immediate, so setup what
284      // is needed for immediate movement
285      if (timeUntilNextToggle_ >= 0)
286        timeUntilNextToggle_ -= deltaTime;
287    }
288
289    // handle HID devices
290    if( processUnbufferedKeyInput() == false )
291        return false;
292    if( processUnbufferedMouseInput() == false )
293        return false;
294
295    // keep rendering
296    return true;
297  }
298
299
300  SceneManager& RunManager::getSceneManager()
301  {
302    return *sceneMgr_;
303  }
304
305  SceneManager* RunManager::getSceneManagerPtr()
306  {
307    return sceneMgr_;
308  }
309
310  BulletManager* RunManager::getBulletManagerPtr()
311  {
312    return bulletManager_;
313  }
314
315  int RunManager::getAmmunitionID(const Ogre::String &ammoName)
316  {
317    Ogre::String ammoTypes[] = { "Energy Cell", "Barrel", "Lead Shot" };
318    int ammoTypesLength = 3;
319
320    for (int i = 0; i < ammoTypesLength; i++)
321    {
322      if (ammoTypes[i] == ammoName)
323        return i;
324    }
325    return -1;
326  }
327
328  int RunManager::getNumberOfAmmos()
329  {
330    return 3;
331  }
332
333
334  /**
335  * Adjust mouse clipping area.
336  * This method is called by Ogre without regards of tick()!
337  * Avoid doing too much in this call.
338  * @param rw render window
339  */
340  void RunManager::windowResized(RenderWindow* rw)
341  {
342    unsigned int width, height, depth;
343    int left, top;
344    rw->getMetrics(width, height, depth, left, top);
345
346    const OIS::MouseState &ms = mouse_->getMouseState();
347    ms.width = width;
348    ms.height = height;
349  }
350
351
352  /**
353  * Unattach OIS before window shutdown (very important under Linux).
354  * Again, avoid computing a lot in this function.
355  * @param rw Render Window
356  */
357  void RunManager::windowClosed(RenderWindow* rw)
358  {
359    //Only close for window that created OIS (the main window in these demos)
360    if( rw == window_ )
361    {
362      if( inputManager_ )
363      {
364        inputManager_->destroyInputObject( mouse_ );
365        inputManager_->destroyInputObject( keyboard_ );
366        inputManager_->destroyInputObject( joystick_ );
367
368        OIS::InputManager::destroyInputSystem(inputManager_);
369        inputManager_ = 0;
370      }
371    }
372  }
373
374  /**
375  * Processes the Keyboard input.
376  * TODO: Use listeners to improve performance.
377  * A lookup table should be implemented to bind any key to a specific action.
378  * @return Return true to keep rendering
379  */
380  bool RunManager::processUnbufferedKeyInput()
381  {
382    using namespace OIS;
383
384    if(keyboard_->isKeyDown(KC_A) || keyboard_->isKeyDown(KC_LEFT))
385      playerShip_->setSideThrust(1);
386    else if(keyboard_->isKeyDown(KC_D) || keyboard_->isKeyDown(KC_RIGHT))
387      playerShip_->setSideThrust(-1);
388    else
389      playerShip_->setSideThrust(0);
390
391    if(keyboard_->isKeyDown(KC_UP) || keyboard_->isKeyDown(KC_W) )
392      playerShip_->setMainThrust(1);
393    else if(keyboard_->isKeyDown(KC_DOWN) || keyboard_->isKeyDown(KC_S) )
394      playerShip_->setMainThrust(-1);
395    else
396      playerShip_->setMainThrust(0);
397
398    if (keyboard_->isKeyDown(KC_C))
399      playerShip_->setYThrust(1);
400    else if (keyboard_->isKeyDown(KC_SPACE))
401      playerShip_->setYThrust(-1);
402    else
403      playerShip_->setYThrust(0);
404
405    if (keyboard_->isKeyDown(KC_G))
406      playerShip_->getMainWeapon()->addAction(BaseWeapon::RELOAD);
407
408    if( keyboard_->isKeyDown(KC_ESCAPE) || keyboard_->isKeyDown(KC_Q) )
409      return false;
410
411    if( keyboard_->isKeyDown(KC_F) && timeUntilNextToggle_ <= 0 )
412    {
413      statsOn_ = !statsOn_;
414      //showDebugOverlay(statsOn_);
415      timeUntilNextToggle_ = 1;
416    }
417
418    if( keyboard_->isKeyDown(KC_T) && timeUntilNextToggle_ <= 0 )
419    {
420      switch(filtering_)
421      {
422      case TFO_BILINEAR:
423        filtering_ = TFO_TRILINEAR;
424        aniso_ = 1;
425        break;
426      case TFO_TRILINEAR:
427        filtering_ = TFO_ANISOTROPIC;
428        aniso_ = 8;
429        break;
430      case TFO_ANISOTROPIC:
431        filtering_ = TFO_BILINEAR;
432        aniso_ = 1;
433        break;
434      default: break;
435      }
436      MaterialManager::getSingleton().setDefaultTextureFiltering(filtering_);
437      MaterialManager::getSingleton().setDefaultAnisotropy(aniso_);
438
439      //showDebugOverlay(statsOn_);
440      timeUntilNextToggle_ = 1;
441    }
442
443    if(keyboard_->isKeyDown(KC_SYSRQ) && timeUntilNextToggle_ <= 0)
444    {
445      std::ostringstream ss;
446      ss << "screenshot_" << ++screenShotCounter_ << ".png";
447      window_->writeContentsToFile(ss.str());
448      timeUntilNextToggle_ = 0.5;
449      debugText_ = "Saved: " + ss.str();
450    }
451
452    if(keyboard_->isKeyDown(KC_R) && timeUntilNextToggle_ <=0)
453    {
454      sceneDetailIndex_ = (sceneDetailIndex_+1)%3 ;
455      switch(sceneDetailIndex_) {
456          case 0 : camera_->setPolygonMode(PM_SOLID); break;
457          case 1 : camera_->setPolygonMode(PM_WIREFRAME); break;
458          case 2 : camera_->setPolygonMode(PM_POINTS); break;
459      }
460      timeUntilNextToggle_ = 0.5;
461    }
462
463    static bool displayCameraDetails = false;
464    if(keyboard_->isKeyDown(KC_P) && timeUntilNextToggle_ <= 0)
465    {
466      displayCameraDetails = !displayCameraDetails;
467      timeUntilNextToggle_ = 0.5;
468      if (!displayCameraDetails)
469        debugText_ = "";
470    }
471
472    // Print camera details
473    if(displayCameraDetails)
474      debugText_ = " | Speed = "
475            + StringConverter::toString(playerShip_->getSpeed())
476            + " | Left Ammo = "
477            + StringConverter::toString(playerShip_
478            ->getMainWeapon()->getAmmoState())
479            + " | Ammo stock = "
480            + StringConverter::toString(playerShip_->getAmmoStock());
481    // debugText_ = "P: " + StringConverter::toString(camera_
482    //      ->getDerivedPosition()) + " " + "O: "
483    //      + StringConverter::toString(camera_->getDerivedOrientation());
484
485    // Return true to continue rendering
486    return true;
487  }
488
489
490  /**
491  * Processes the Mouse input.
492  * TODO: Use listeners to improve performance.
493  * A lookup table should be implemented to bind ANY button or movement
494  * to a specific action.
495  * @return Return true to keep rendering
496  */
497  bool RunManager::processUnbufferedMouseInput()
498  {
499    using namespace OIS;
500
501    const MouseState &ms = mouse_->getMouseState();
502
503    if (ms.buttonDown(MB_Left))
504      playerShip_->getMainWeapon()->primaryFireRequest();
505
506    if (ms.buttonDown(MB_Right))
507      playerShip_->getMainWeapon()->secondaryFireRequest();
508
509    playerShip_->turnUpAndDown(Radian(ms.Y.rel * mouseSensitivity_));
510    playerShip_->turnLeftAndRight(Radian(ms.X.rel * mouseSensitivity_));
511
512    // keep rendering
513    return true;
514  }
515
516  /**
517  * Show the debug overlay of desired.
518  * @param show Whether or not to show the debug overlay
519  */
520  void RunManager::showDebugOverlay(bool show)
521  {
522    if (debugOverlay_)
523    {
524      if (show)
525        debugOverlay_->show();
526      else
527        debugOverlay_->hide();
528    }
529  }
530
531
532  /**
533  * Show stats (e.g. FPS) in the left lower corner of the screen.
534  * Copied from the ExampleFrameListener.h in the Ogre SDK
535  */
536  void RunManager::updateStats(void)
537  {
538    static String currFps = "Current FPS: ";
539    static String avgFps = "Average FPS: ";
540    static String bestFps = "Best FPS: ";
541    static String worstFps = "Worst FPS: ";
542    static String tris = "Triangle Count: ";
543    static String batches = "Batch Count: ";
544
545    // update stats when necessary
546    try {
547      OverlayElement* guiAvg = OverlayManager::getSingleton()
548        .getOverlayElement("Core/AverageFps");
549      OverlayElement* guiCurr = OverlayManager::getSingleton()
550        .getOverlayElement("Core/CurrFps");
551      OverlayElement* guiBest = OverlayManager::getSingleton()
552        .getOverlayElement("Core/BestFps");
553      OverlayElement* guiWorst = OverlayManager::getSingleton()
554        .getOverlayElement("Core/WorstFps");
555
556      const RenderTarget::FrameStats& stats = window_->getStatistics();
557      guiAvg->setCaption(avgFps + StringConverter::toString(stats.avgFPS));
558      guiCurr->setCaption(currFps + StringConverter::toString(stats.lastFPS));
559      guiBest->setCaption(bestFps + StringConverter::toString(stats.bestFPS)
560        +" "+StringConverter::toString(stats.bestFrameTime)+" ms");
561      guiWorst->setCaption(worstFps + StringConverter::toString(stats.worstFPS)
562        +" "+StringConverter::toString(stats.worstFrameTime)+" ms");
563
564      OverlayElement* guiTris = OverlayManager::getSingleton()
565        .getOverlayElement("Core/NumTris");
566      guiTris->setCaption(tris + StringConverter::toString(stats.triangleCount));
567
568      OverlayElement* guiBatches = OverlayManager::getSingleton()
569        .getOverlayElement("Core/NumBatches");
570      guiBatches->setCaption(batches
571        + StringConverter::toString(stats.batchCount));
572
573      OverlayElement* guiDbg = OverlayManager::getSingleton()
574        .getOverlayElement("Core/DebugText");
575      guiDbg->setCaption(debugText_);
576    }
577    catch(...) { /* ignore */ }
578  }
579
580
581  /**
582  * Simple camera creator.
583  * playerShip_Node->attachObject(camera_) should no be here! This is what the camera
584  * manager is for. Right now, this method should do just fine, setting the
585  * cam behind the ship.
586  */
587  void RunManager::createCamera(void)
588  {
589    camera_ = sceneMgr_->createCamera("PlayerCam");
590    playerShip_->getRootNode()->getSceneNode()->attachObject(camera_);
591    camera_->setNearClipDistance(5);
592    camera_->setPosition(Vector3(0,10,500));
593    camera_->lookAt(Vector3(0,0,0));
594  }
595
596  /**
597  * Simple viewport creator.
598  * For now the viewport uses the entire render window and is based on the one
599  * camera created so far.
600  */
601  void RunManager::createViewports(void)
602  {
603    // Create one viewport, entire window
604    Viewport* vp = window_->addViewport(camera_);
605    vp->setBackgroundColour(ColourValue(0,0,0));
606
607    // Alter the camera aspect ratio to match the viewport
608    camera_->setAspectRatio(
609      Real(vp->getActualWidth()) / Real(vp->getActualHeight()));
610  }
611
612}
Note: See TracBrowser for help on using the repository browser.