Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/network/src/orxonox/Orxonox.cc @ 922

Last change on this file since 922 was 922, checked in by rgrieder, 16 years ago
  • created InputEventListener and InputEvent
  • escape key now works through the InputHandler
  • the concept will soon be replaced by a new one this is more of a 'svn save' ;)
File size: 13.4 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
8 *   modify it under the terms of the GNU General Public License
9 *   as published by the Free Software Foundation; either version 2
10 *   of the License, or (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, write to the Free Software
19 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20 *
21 *   Author:
22 *      Benjamin Knecht <beni_at_orxonox.net>, (C) 2007
23 *   Co-authors:
24 *      ...
25 *
26 */
27
28/**
29 @file  Orxonox.cc
30 @brief Orxonox Main Class
31 */
32
33// Precompiled Headers
34#include "OrxonoxStableHeaders.h"
35
36//****** OGRE ******
37#include <OgreException.h>
38#include <OgreRoot.h>
39#include <OgreRenderWindow.h>
40#include <OgreTextureManager.h>
41#include <OgreResourceGroupManager.h>
42#include <OgreConfigFile.h>
43#include <OgreOverlay.h>
44#include <OgreOverlayManager.h>
45#include <OgreTimer.h>
46#include <OgreWindowEventUtilities.h>
47
48//****** OIS *******
49#include <OIS/OIS.h>
50
51//****** STD *******
52#include <iostream>
53#include <exception>
54
55//***** ORXONOX ****
56//misc
57#include "util/Sleep.h"
58
59// audio
60#include "audio/AudioManager.h"
61
62// network
63#include "network/Server.h"
64#include "network/Client.h"
65network::Client *client_g;
66network::Server *server_g;
67
68// objects
69#include "tools/Timer.h"
70#include "core/ArgReader.h"
71#include "core/Debug.h"
72#include "core/Factory.h"
73#include "core/Loader.h"
74#include "core/Tickable.h"
75#include "hud/HUD.h"
76#include "objects/weapon/BulletManager.h"
77
78#include "InputHandler.h"
79
80#include "Orxonox.h"
81
82namespace orxonox
83{
84  /// init static singleton reference of Orxonox
85  Orxonox* Orxonox::singletonRef_ = NULL;
86
87  /**
88   * create a new instance of Orxonox
89   */
90  Orxonox::Orxonox()
91  {
92    this->ogre_ = new GraphicsEngine();
93    this->dataPath_ = "";
94    this->auMan_ = 0;
95    this->singletonRef_ = 0;
96    //this->keyboard_ = 0;
97    //this->mouse_ = 0;
98    //this->inputManager_ = 0;
99    this->inputHandler_ = 0;
100    this->frameListener_ = 0;
101    this->root_ = 0;
102    // turn frame smoothing on by setting a value different from 0
103    this->frameSmoothingTime_ = 0.0f;
104    this->bAbort_ = false;
105  }
106
107  /**
108   * destruct Orxonox
109   */
110  Orxonox::~Orxonox()
111  {
112    // nothing to delete as for now
113  }
114
115  /**
116   * initialization of Orxonox object
117   * @param argc argument counter
118   * @param argv list of argumenst
119   * @param path path to config (in home dir or something)
120   */
121  void Orxonox::init(int argc, char **argv, std::string path)
122  {
123    //TODO: find config file (assuming executable directory)
124    //TODO: read config file
125    //TODO: give config file to Ogre
126    std::string mode;
127   
128   
129    ArgReader ar = ArgReader(argc, argv);
130    ar.checkArgument("mode", mode, false);
131    ar.checkArgument("data", this->dataPath_, false);
132    ar.checkArgument("ip", serverIp_, false);
133    if(ar.errorHandling()) die();
134    if(mode == std::string("client"))
135    {
136      mode_ = CLIENT;
137      clientInit(path);
138    }
139    else if(mode== std::string("server")){
140      mode_ = SERVER;
141      serverInit(path);
142    }
143    else{
144      mode_ = STANDALONE;
145      standaloneInit(path);
146    }
147  }
148
149 
150  /**
151   * start modules
152   */
153  void Orxonox::start()
154  {
155    switch(mode_){
156    case CLIENT:
157      clientStart();
158      break;
159    case SERVER:
160      serverStart();
161      break;
162    default:
163      standaloneStart();
164    }
165  }
166 
167  void Orxonox::clientStart(){
168    ogre_->startRender();
169    Factory::createClassHierarchy();
170   
171   
172    auMan_ = new audio::AudioManager();
173
174    bulletMgr_ = new BulletManager();
175   
176    Ogre::Overlay* hudOverlay = Ogre::OverlayManager::getSingleton().getByName("Orxonox/HUD1.2");
177    HUD* orxonoxHud;
178    orxonoxHud = new HUD();
179    orxonoxHud->setEnergyValue(20);
180    orxonoxHud->setEnergyDistr(20,20,60);
181    hudOverlay->show();
182   
183    client_g->establishConnection();
184    client_g->tick(0);
185   
186   
187    //setupInputSystem();
188   
189    startRenderLoop();
190  }
191 
192  void Orxonox::serverStart(){
193    //TODO: start modules
194    ogre_->startRender();
195    //TODO: run engine
196    Factory::createClassHierarchy();
197    createScene();
198    setupScene();
199    setupInputSystem();
200   
201    server_g->open();
202   
203    startRenderLoop();
204  }
205 
206  void Orxonox::standaloneStart(){
207    //TODO: start modules
208    ogre_->startRender();
209    //TODO: run engine
210    Factory::createClassHierarchy();
211    createScene();
212    setupScene();
213    setupInputSystem();
214   
215    startRenderLoop();
216  }
217
218  /**
219   * @return singleton object
220   */
221  Orxonox* Orxonox::getSingleton()
222  {
223    if (!singletonRef_)
224      singletonRef_ = new Orxonox();
225    return singletonRef_;
226  }
227
228  /**
229   * error kills orxonox
230   */
231  void Orxonox::die(/* some error code */)
232  {
233    //TODO: destroy and destruct everything and print nice error msg
234    delete this;
235  }
236
237  /**
238    Asks the mainloop nicely to abort.
239  */
240  void Orxonox::abortRequest()
241  {
242    bAbort_ = true;
243  }
244
245
246  void Orxonox::serverInit(std::string path)
247  {
248    COUT(2) << "initialising server" << std::endl;
249   
250    ogre_->setConfigPath(path);
251    ogre_->setup();
252    root_ = ogre_->getRoot();
253    if(!ogre_->load()) die(/* unable to load */);
254   
255    server_g = new network::Server();
256  }
257
258  void Orxonox::clientInit(std::string path)
259  {
260    COUT(2) << "initialising client" << std::endl;\
261   
262    ogre_->setConfigPath(path);
263    ogre_->setup();
264    if(serverIp_.compare("")==0)
265      client_g = new network::Client();
266    else
267      client_g = new network::Client(serverIp_, NETWORK_PORT);
268    if(!ogre_->load()) die(/* unable to load */);
269  }
270 
271  void Orxonox::standaloneInit(std::string path)
272  {
273    COUT(2) << "initialising standalone mode" << std::endl;
274   
275    ogre_->setConfigPath(path);
276    ogre_->setup();
277    root_ = ogre_->getRoot();
278    if(!ogre_->load()) die(/* unable to load */);
279  }
280
281  void Orxonox::defineResources()
282  {
283    std::string secName, typeName, archName;
284    Ogre::ConfigFile cf;
285#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE
286    cf.load(macBundlePath() + "/Contents/Resources/resources.cfg");
287#else
288    cf.load(dataPath_ + "resources.cfg");
289#endif
290
291    Ogre::ConfigFile::SectionIterator seci = cf.getSectionIterator();
292    while (seci.hasMoreElements())
293    {
294      secName = seci.peekNextKey();
295      Ogre::ConfigFile::SettingsMultiMap *settings = seci.getNext();
296      Ogre::ConfigFile::SettingsMultiMap::iterator i;
297      for (i = settings->begin(); i != settings->end(); ++i)
298      {
299        typeName = i->first;
300        archName = i->second;
301#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE
302        Ogre::ResourceGroupManager::getSingleton().addResourceLocation( std::string(macBundlePath() + "/" + archName), typeName, secName);
303#else
304        Ogre::ResourceGroupManager::getSingleton().addResourceLocation( archName, typeName, secName);
305#endif
306      }
307    }
308  }
309
310  void Orxonox::setupRenderSystem()
311  {
312    if (!root_->restoreConfig() && !root_->showConfigDialog())
313      throw Ogre::Exception(52, "User canceled the config dialog!", "OrxApplication::setupRenderSystem()");
314  }
315
316  void Orxonox::createRenderWindow()
317  {
318    root_->initialise(true, "OrxonoxV2");
319  }
320
321  void Orxonox::initializeResourceGroups()
322  {
323    Ogre::TextureManager::getSingleton().setDefaultNumMipmaps(5);
324    Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
325  }
326
327  void Orxonox::createScene(void)
328  {
329        // Init audio
330    auMan_ = new audio::AudioManager();
331
332    bulletMgr_ = new BulletManager();
333
334    // load this file from config
335//    loader_ = new loader::LevelLoader("sample.oxw");
336//    loader_->loadLevel();
337    Level* startlevel = new Level("levels/sample.oxw");
338    Loader::open(startlevel);
339
340    Ogre::Overlay* hudOverlay = Ogre::OverlayManager::getSingleton().getByName("Orxonox/HUD1.2");
341    //HUD* orxonoxHud;
342    orxonoxHUD_ = new HUD();
343    orxonoxHUD_->setEnergyValue(20);
344    orxonoxHUD_->setEnergyDistr(20,20,60);
345    hudOverlay->show();
346
347        /*
348    auMan_->ambientAdd("a1");
349    auMan_->ambientAdd("a2");
350    auMan_->ambientAdd("a3");
351                                //auMan->ambientAdd("ambient1");
352    auMan_->ambientStart();*/
353  }
354
355
356  void Orxonox::setupScene()
357  {
358//    SceneManager *mgr = ogre_->getSceneManager();
359
360
361//    SceneNode* node = (SceneNode*)mgr->getRootSceneNode()->getChild("OgreHeadNode");
362//     SceneNode *node = mgr->getRootSceneNode()->createChildSceneNode("OgreHeadNode", Vector3(0,0,0));
363
364
365/*
366    particle::ParticleInterface *e = new particle::ParticleInterface(mgr,"engine","Orxonox/strahl");
367    e->particleSystem_->setParameter("local_space","true");
368    e->setPositionOfEmitter(0, Vector3(0,-10,0));
369    e->setDirection(Vector3(0,0,-1));
370    e->addToSceneNode(node);
371*/
372  }
373
374  /**
375    @brief Calls the InputHandler which sets up the input devices.
376    The render window width and height are used to set up the mouse movement.
377  */
378  void Orxonox::setupInputSystem()
379  {
380    inputHandler_ = InputHandler::getSingleton();
381    inputHandler_->initialise(ogre_->getWindowHandle(),
382          ogre_->getWindowWidth(), ogre_->getWindowHeight());
383  }
384
385  /**
386    Main loop of the orxonox game.
387    This is a new solution, using the ogre engine instead of being used by it.
388    An alternative solution would be to simply use the timer of the Root object,
389    but that implies using Ogre in any case. There would be no way to test
390    our code without the help of the root object.
391    There's even a chance that we can dispose of the root object entirely
392    in server mode.
393    About the loop: The design is almost exactly like the one in ogre, so that
394    if any part of ogre registers a framelisteners, it will still behave
395    correctly. Furthermore I have taken over the time smoothing feature from
396    ogre. If turned on (see orxonox constructor), it will calculate the dt_n by
397    means of the recent most dt_n-1, dt_n-2, etc.
398  */
399  void Orxonox::startRenderLoop()
400  {
401    // use the ogre timer class to measure time.
402    Ogre::Timer *timer = new Ogre::Timer();
403    timer->reset();
404
405    // Contains the times of recently fired events
406    std::deque<unsigned long> eventTimes[3];
407    // Clear event times
408    for (int i = 0; i < 3; ++i)
409      eventTimes[i].clear();
410
411          while (!bAbort_)
412          {
413                  // Pump messages in all registered RenderWindows
414      Ogre::WindowEventUtilities::messagePump();
415
416      // get current time
417      unsigned long now = timer->getMilliseconds();
418
419      // create an event to pass to the frameStarted method in ogre
420      Ogre::FrameEvent evt;
421      evt.timeSinceLastEvent = calculateEventTime(now, eventTimes[0]);
422      evt.timeSinceLastFrame = calculateEventTime(now, eventTimes[1]);
423
424      // show the current time in the HUD
425      orxonoxHUD_->setTime((int)now, 0);
426
427      // don't forget to call _fireFrameStarted in ogre to make sure
428      // everything goes smoothly
429      if (!ogre_->getRoot()->_fireFrameStarted(evt))
430        break;
431
432      // Iterate through all Tickables and call their tick(dt) function
433      for (Iterator<Tickable> it = ObjectList<Tickable>::start(); it; )
434        (it++)->tick((float)evt.timeSinceLastFrame);
435
436      if (mode_ != SERVER)
437      {
438        // only render in non-server mode
439        ogre_->getRoot()->_updateAllRenderTargets();
440      }
441
442      // get current time
443      now = timer->getMilliseconds();
444
445      // create an event to pass to the frameEnded method in ogre
446      evt.timeSinceLastEvent = calculateEventTime(now, eventTimes[0]);
447      evt.timeSinceLastFrame = calculateEventTime(now, eventTimes[2]);
448
449      // again, just to be sure ogre works fine
450      if (!ogre_->getRoot()->_fireFrameEnded(evt))
451        break;
452          }
453  }
454
455  /**
456    Method for calculating the average time between recently fired events.
457    Code directly taken from OgreRoot.cc
458    @param now The current time in ms.
459    @param type The type of event to be considered.
460  */
461  float Orxonox::calculateEventTime(unsigned long now, std::deque<unsigned long> &times)
462  {
463    // Calculate the average time passed between events of the given type
464    // during the last mFrameSmoothingTime seconds.
465
466    times.push_back(now);
467
468    if(times.size() == 1)
469      return 0;
470
471    // Times up to mFrameSmoothingTime seconds old should be kept
472    unsigned long discardThreshold =
473      static_cast<unsigned long>(frameSmoothingTime_ * 1000.0f);
474
475    // Find the oldest time to keep
476    std::deque<unsigned long>::iterator it = times.begin(),
477      end = times.end()-2; // We need at least two times
478    while(it != end)
479    {
480      if (now - *it > discardThreshold)
481        ++it;
482      else
483        break;
484    }
485
486    // Remove old times
487    times.erase(times.begin(), it);
488
489    return (float)(times.back() - times.front()) / ((times.size()-1) * 1000);
490  }
491
492  void Orxonox::eventOccured(InputEvent &evt)
493  {
494    if (evt.id == 1)
495      this->abortRequest();
496  }
497}
Note: See TracBrowser for help on using the repository browser.