Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/hud2/src/orxonox/Orxonox.cc @ 1318

Last change on this file since 1318 was 1099, checked in by chaiy, 17 years ago

Bars finally work

File size: 11.8 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 <OgreFrameListener.h>
39#include <OgreOverlay.h>
40#include <OgreOverlayManager.h>
41#include <OgreTimer.h>
42#include <OgreWindowEventUtilities.h>
43
44//****** STD *******
45//#include <iostream>
46//#include <exception>
47#include <deque>
48
49//***** ORXONOX ****
50//misc
51//#include "util/Sleep.h"
52#include "util/ArgReader.h"
53
54// audio
55#include "audio/AudioManager.h"
56
57// network
58#include "network/Server.h"
59#include "network/Client.h"
60network::Client *client_g;
61network::Server *server_g;
62
63// objects
64#include "core/Debug.h"
65#include "core/Factory.h"
66#include "core/Loader.h"
67#include "core/Tickable.h"
68#include "hud/HUD.h"
69#include "tools/Timer.h"
70#include "objects/weapon/BulletManager.h"
71
72#include "core/InputManager.h"
73
74#include "Orxonox.h"
75
76namespace orxonox
77{
78  /**
79    @brief Reference to the only instance of the class.
80  */
81  Orxonox *Orxonox::singletonRef_s = 0;
82
83  /**
84   * create a new instance of Orxonox
85   */
86  Orxonox::Orxonox()
87  {
88    this->ogre_ = new GraphicsEngine();
89    this->timer_ = 0;
90    this->dataPath_ = "";
91    this->auMan_ = 0;
92    this->inputHandler_ = 0;
93    //this->root_ = 0;
94    // turn on frame smoothing by setting a value different from 0
95    this->frameSmoothingTime_ = 0.0f;
96    this->bAbort_ = false;
97  }
98
99  /**
100   * destruct Orxonox
101   */
102  Orxonox::~Orxonox()
103  {
104    // keep in mind: the order of deletion is very important!
105    if (this->bulletMgr_)
106      delete this->bulletMgr_;
107    if (this->orxonoxHUD_)
108      delete this->orxonoxHUD_;
109    Loader::close();
110    InputManager::destroySingleton();
111    if (this->auMan_)
112      delete this->auMan_;
113    if (this->timer_)
114      delete this->timer_;
115    if (this->ogre_)
116      delete this->ogre_;
117
118    if (client_g)
119      delete client_g;
120    if (server_g)
121      delete server_g;
122  }
123
124  /**
125   * error kills orxonox
126   */
127  void Orxonox::abortImmediate(/* some error code */)
128  {
129    //TODO: destroy and destruct everything and print nice error msg
130    delete this;
131  }
132
133  /**
134    Asks the mainloop nicely to abort.
135  */
136  void Orxonox::abortRequest()
137  {
138    bAbort_ = true;
139  }
140
141  /**
142   * @return singleton object
143   */
144  Orxonox* Orxonox::getSingleton()
145  {
146    if (!singletonRef_s)
147      singletonRef_s = new Orxonox();
148    return singletonRef_s;
149    //static Orxonox theOnlyInstance;
150    //return &theOnlyInstance;
151  }
152
153  /**
154    @brief Destroys the Orxonox singleton.
155  */
156  void Orxonox::destroySingleton()
157  {
158    if (singletonRef_s)
159      delete singletonRef_s;
160    singletonRef_s = 0;
161  }
162
163  /**
164   * initialization of Orxonox object
165   * @param argc argument counter
166   * @param argv list of argumenst
167   * @param path path to config (in home dir or something)
168   */
169  void Orxonox::init(int argc, char **argv, std::string path)
170  {
171    //TODO: find config file (assuming executable directory)
172    //TODO: read config file
173    //TODO: give config file to Ogre
174    std::string mode;
175
176    ArgReader ar(argc, argv);
177    ar.checkArgument("mode", mode, false);
178    ar.checkArgument("data", this->dataPath_, false);
179    ar.checkArgument("ip", serverIp_, false);
180    if(ar.errorHandling()) abortImmediate();
181    if(mode == std::string("client"))
182    {
183      mode_ = CLIENT;
184      clientInit(path);
185    }
186    else if(mode== std::string("server")){
187      mode_ = SERVER;
188      serverInit(path);
189    }
190    else{
191      mode_ = STANDALONE;
192      standaloneInit(path);
193    }
194  }
195
196  void Orxonox::serverInit(std::string path)
197  {
198    COUT(2) << "initialising server" << std::endl;
199   
200    ogre_->setConfigPath(path);
201    ogre_->setup();
202    //root_ = ogre_->getRoot();
203    if(!ogre_->load(this->dataPath_)) abortImmediate(/* unable to load */);
204   
205    server_g = new network::Server();
206  }
207
208  void Orxonox::clientInit(std::string path)
209  {
210    COUT(2) << "initialising client" << std::endl;\
211   
212    ogre_->setConfigPath(path);
213    ogre_->setup();
214    if(serverIp_.compare("")==0)
215      client_g = new network::Client();
216    else
217      client_g = new network::Client(serverIp_, NETWORK_PORT);
218    if(!ogre_->load(this->dataPath_)) abortImmediate(/* unable to load */);
219  }
220 
221  void Orxonox::standaloneInit(std::string path)
222  {
223    COUT(2) << "initialising standalone mode" << std::endl;
224   
225    ogre_->setConfigPath(path);
226    ogre_->setup();
227    //root_ = ogre_->getRoot();
228    if(!ogre_->load(this->dataPath_)) abortImmediate(/* unable to load */);
229  }
230 
231  /**
232   * start modules
233   */
234  void Orxonox::start()
235  {
236    switch(mode_){
237    case CLIENT:
238      clientStart();
239      break;
240    case SERVER:
241      serverStart();
242      break;
243    default:
244      standaloneStart();
245    }
246  }
247 
248  void Orxonox::clientStart(){
249    ogre_->initialise();
250    Factory::createClassHierarchy();
251   
252   
253    auMan_ = new audio::AudioManager();
254
255    bulletMgr_ = new BulletManager();
256   
257    //Ogre::Overlay* hudOverlay = Ogre::OverlayManager::getSingleton().getByName("Orxonox/HUD1.2");
258    //HUD* orxonoxHud;
259    orxonoxHUD_ = new HUD(1);
260    //orxonoxHud->setEnergyValue(20);
261    //orxonoxHud->setEnergyDistr(20,20,60);
262    //hudOverlay->show();
263   
264    client_g->establishConnection();
265    client_g->tick(0);
266   
267   
268    //setupInputSystem();
269   
270    startRenderLoop();
271  }
272 
273  void Orxonox::serverStart(){
274    //TODO: start modules
275    ogre_->initialise();
276    //TODO: run engine
277    Factory::createClassHierarchy();
278    createScene();
279    setupInputSystem();
280   
281    server_g->open();
282   
283    startRenderLoop();
284  }
285 
286  void Orxonox::standaloneStart(){
287    //TODO: start modules
288    ogre_->initialise();
289    //TODO: run engine
290    Factory::createClassHierarchy();
291    createScene();
292    setupInputSystem();
293   
294    startRenderLoop();
295  }
296
297  void Orxonox::createScene(void)
298  {
299          // Init audio
300    auMan_ = new audio::AudioManager();
301
302    bulletMgr_ = new BulletManager();
303
304    // load this file from config
305    Level* startlevel = new Level("levels/sample.oxw");
306    Loader::open(startlevel);
307
308    //Ogre::Overlay* hudOverlay = Ogre::OverlayManager::getSingleton().getByName("Orxonox/HUD1.2");
309    orxonoxHUD_ = new HUD(1);
310    //orxonoxHUD_->setEnergyValue(20);
311    //orxonoxHUD_->setEnergyDistr(20,20,60);
312    //hudOverlay->show();
313   
314   
315
316        /*
317    auMan_->ambientAdd("a1");
318    auMan_->ambientAdd("a2");
319    auMan_->ambientAdd("a3");
320    //auMan->ambientAdd("ambient1");
321    auMan_->ambientStart();
322  */
323  }
324
325  /**
326    @brief Calls the InputHandler which sets up the input devices.
327    The render window width and height are used to set up the mouse movement.
328  */
329  void Orxonox::setupInputSystem()
330  {
331    inputHandler_ = InputManager::getSingleton();
332    if (!inputHandler_->initialise(ogre_->getWindowHandle(),
333          ogre_->getWindowWidth(), ogre_->getWindowHeight()))
334      abortImmediate();
335  }
336
337  /**
338    Main loop of the orxonox game.
339    This is a new solution, using the ogre engine instead of being used by it.
340    An alternative solution would be to simply use the timer of the Root object,
341    but that implies using Ogre in any case. There would be no way to test
342    our code without the help of the root object.
343    There's even a chance that we can dispose of the root object entirely
344    in server mode.
345    About the loop: The design is almost exactly like the one in ogre, so that
346    if any part of ogre registers a framelisteners, it will still behave
347    correctly. Furthermore I have taken over the time smoothing feature from
348    ogre. If turned on (see orxonox constructor), it will calculate the dt_n by
349    means of the recent most dt_n-1, dt_n-2, etc.
350  */
351  void Orxonox::startRenderLoop()
352  {
353    // use the ogre timer class to measure time.
354    if (!timer_)
355      timer_ = new Ogre::Timer();
356    timer_->reset();
357
358    // Contains the times of recently fired events
359    std::deque<unsigned long> eventTimes[3];
360    // Clear event times
361    for (int i = 0; i < 3; ++i)
362      eventTimes[i].clear();
363
364          while (!bAbort_)
365          {
366                  // Pump messages in all registered RenderWindows
367      Ogre::WindowEventUtilities::messagePump();
368
369      // get current time
370      unsigned long now = timer_->getMilliseconds();
371
372      // create an event to pass to the frameStarted method in ogre
373      Ogre::FrameEvent evt;
374      evt.timeSinceLastEvent = calculateEventTime(now, eventTimes[0]);
375      evt.timeSinceLastFrame = calculateEventTime(now, eventTimes[1]);
376
377      // show the current time in the HUD
378      //orxonoxHUD_->setTime((int)now, 0);
379//      orxonoxHUD_->energyCounter->reset(20);
380
381
382      // Iterate through all Tickables and call their tick(dt) function
383      for (Iterator<Tickable> it = ObjectList<Tickable>::start(); it; )
384        (it++)->tick((float)evt.timeSinceLastFrame);
385
386      // don't forget to call _fireFrameStarted in ogre to make sure
387      // everything goes smoothly
388      ogre_->frameStarted(evt);
389
390      if (mode_ != SERVER)
391        ogre_->renderOneFrame(); // only render in non-server mode
392
393      // get current time
394      now = timer_->getMilliseconds();
395
396      // create an event to pass to the frameEnded method in ogre
397      evt.timeSinceLastEvent = calculateEventTime(now, eventTimes[0]);
398      evt.timeSinceLastFrame = calculateEventTime(now, eventTimes[2]);
399
400      // again, just to be sure ogre works fine
401      ogre_->frameEnded(evt);
402          }
403  }
404
405  /**
406    Method for calculating the average time between recently fired events.
407    Code directly taken from OgreRoot.cc
408    @param now The current time in ms.
409    @param type The type of event to be considered.
410  */
411  float Orxonox::calculateEventTime(unsigned long now, std::deque<unsigned long> &times)
412  {
413    // Calculate the average time passed between events of the given type
414    // during the last mFrameSmoothingTime seconds.
415
416    times.push_back(now);
417
418    if(times.size() == 1)
419      return 0;
420
421    // Times up to mFrameSmoothingTime seconds old should be kept
422    unsigned long discardThreshold =
423      static_cast<unsigned long>(frameSmoothingTime_ * 1000.0f);
424
425    // Find the oldest time to keep
426    std::deque<unsigned long>::iterator it = times.begin(),
427      end = times.end()-2; // We need at least two times
428    while(it != end)
429    {
430      if (now - *it > discardThreshold)
431        ++it;
432      else
433        break;
434    }
435
436    // Remove old times
437    times.erase(times.begin(), it);
438
439    return (float)(times.back() - times.front()) / ((times.size()-1) * 1000);
440  }
441
442  /**
443    @brief Test method for the InputHandler.
444    But: Is actually responsible for catching an exit event..
445  */
446  void Orxonox::eventOccured(InputEvent &evt)
447  {
448    if (evt.id == 1)
449      this->abortRequest();
450  }
451}
Note: See TracBrowser for help on using the repository browser.