Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/core6/src/libraries/core/Game.h @ 10843

Last change on this file since 10843 was 9578, checked in by landauf, 12 years ago

made some classes (mostly singletons) inherit from Configurable instead of OrxonoxClass when they only need the config value facilities

  • Property svn:eol-style set to native
File size: 7.9 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Reto Grieder
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29/**
30@file
31@ingroup Management CoreGame
32@brief
33    Declaration of Game Singleton which is responsible for running the game.
34 */
35
36#ifndef _Game_H__
37#define _Game_H__
38
39#include "CorePrereqs.h"
40
41#include <cassert>
42#include <list>
43#include <map>
44#include <string>
45#include <vector>
46#include <boost/shared_ptr.hpp>
47#include <boost/preprocessor/cat.hpp>
48
49#include "util/Output.h"
50#include "util/DestructionHelper.h"
51#include "util/Singleton.h"
52#include "config/Configurable.h"
53
54/**
55@brief
56    Adds a new GameState to the Game. The second parameter is the name as string
57    and every following parameter is a constructor argument (which is usually non existent)
58*/
59#define DeclareGameState(className, stateName, bIgnoreTickTime, bGraphicsMode) \
60    static bool BOOST_PP_CAT(bGameStateDummy_##className, __UNIQUE_NUMBER__) = orxonox::Game::declareGameState<className>(#className, stateName, bIgnoreTickTime, bGraphicsMode)
61// tolua_begin
62namespace orxonox
63{
64// tolua_end
65
66    //! Helper object required before GameStates are being constructed
67    struct GameStateInfo
68    {
69        std::string stateName;
70        std::string className;
71        bool bIgnoreTickTime;
72        bool bGraphicsMode;
73    };
74
75    /**
76    @brief
77        Main class responsible for running the game.
78    @remark
79        You should only create this singleton once because it owns the Core class! (see remark there)
80    */
81// tolua_begin
82    class _CoreExport Game
83// tolua_end
84        : public Singleton<Game>, public Configurable
85    { // tolua_export
86        friend class Singleton<Game>;
87        typedef std::vector<shared_ptr<GameState> > GameStateVector;
88        typedef std::map<std::string, shared_ptr<GameState> > GameStateMap;
89        typedef shared_ptr<GameStateTreeNode> GameStateTreeNodePtr;
90
91    public:
92        Game(const std::string& cmdLine);
93
94        //! Leave empty and use cleanup() instead
95        ~Game() {}
96        /// Destructor that also executes when object fails to construct
97        void destroy();
98
99        void setConfigValues();
100
101        void setStateHierarchy(const std::string& str);
102        shared_ptr<GameState> getState(const std::string& name);
103
104        void run();
105        void stop();
106
107        static Game& getInstance(){ return Singleton<Game>::getInstance(); } // tolua_export
108
109        void requestState(const std::string& name); //tolua_export
110        void requestStates(const std::string& names); //tolua_export
111        void popState(); //tolua_export
112
113        const Clock& getGameClock() { return *this->gameClock_; }
114
115        float getAvgTickTime() { return this->avgTickTime_; }
116        float getAvgFPS()      { return this->avgFPS_; }
117
118        void subtractTickTime(int32_t length);
119
120        template <class T>
121        static bool declareGameState(const std::string& className, const std::string& stateName, bool bIgnoreTickTime, bool bConsoleMode);
122
123    private:
124        class _CoreExport GameStateFactory
125        {
126        public:
127            virtual ~GameStateFactory() { }
128            static shared_ptr<GameState> fabricate(const GameStateInfo& info);
129            template <class T>
130            static void createFactory(const std::string& className)
131                { getFactories()[className].reset(new TemplateGameStateFactory<T>()); }
132
133            virtual shared_ptr<GameState> fabricateInternal(const GameStateInfo& info) = 0;
134            static std::map<std::string, shared_ptr<GameStateFactory> >& getFactories();
135        };
136        template <class T>
137        class TemplateGameStateFactory : public GameStateFactory
138        {
139        public:
140            shared_ptr<GameState> fabricateInternal(const GameStateInfo& info)
141                { return shared_ptr<GameState>(new T(info)); }
142        };
143
144        struct StatisticsTickInfo
145        {
146            uint64_t    tickTime;
147            uint32_t    tickLength;
148        };
149
150        Game(Game&); // don't mess with singletons
151
152        void loadGraphics();
153        void unloadGraphics();
154
155        void parseStates(std::vector<std::pair<std::string, int> >::const_iterator& it, shared_ptr<GameStateTreeNode> currentNode);
156        bool checkState(const std::string& name) const;
157        void loadState(const std::string& name);
158        void unloadState(const std::string& name);
159
160        // Main loop structuring
161        void updateGameStateStack();
162        void updateGameStates();
163        void updateStatistics();
164        void updateFPSLimiter();
165
166        // ScopeGuard helper function
167        void resetChangingState() { this->bChangingState_ = false; }
168
169        Clock*                             gameClock_;
170        Core*                              core_;
171
172        GameStateMap                       constructedStates_;
173        GameStateVector                    loadedStates_;
174        GameStateTreeNodePtr               rootStateNode_;
175        GameStateTreeNodePtr               loadedTopStateNode_;
176        std::vector<GameStateTreeNodePtr>  requestedStateNodes_;
177
178        bool                               bChangingState_;
179        bool                               bAbort_;
180
181        // variables for time statistics
182        uint64_t                           statisticsStartTime_;
183        std::list<StatisticsTickInfo>      statisticsTickTimes_;
184        uint32_t                           periodTime_;
185        uint32_t                           periodTickTime_;
186        float                              avgFPS_;
187        float                              avgTickTime_;
188        int                                excessSleepTime_;
189        unsigned int                       minimumSleepTime_;
190
191        // config values
192        unsigned int                       statisticsRefreshCycle_;
193        unsigned int                       statisticsAvgLength_;
194        unsigned int                       fpsLimit_;
195
196        /// Helper object that executes the surrogate destructor destroy()
197        DestructionHelper<Game>            destructionHelper_;
198
199        static std::map<std::string, GameStateInfo> gameStateDeclarations_s;
200        static Game* singletonPtr_s;        //!< Pointer to the Singleton
201    }; //tolua_export
202
203    template <class T>
204    /*static*/ bool Game::declareGameState(const std::string& className, const std::string& stateName, bool bIgnoreTickTime, bool bGraphicsMode)
205    {
206        std::map<std::string, GameStateInfo>::const_iterator it = gameStateDeclarations_s.find(stateName);
207        if (it == gameStateDeclarations_s.end())
208        {
209            GameStateInfo& info = gameStateDeclarations_s[stateName];
210            info.stateName = stateName;
211            info.className = className;
212            info.bIgnoreTickTime = bIgnoreTickTime;
213            info.bGraphicsMode = bGraphicsMode;
214        }
215        else
216        {
217            orxout(internal_warning) << "Cannot declare two GameStates with the same name." << endl;
218            orxout(internal_warning) << "Ignoring second one ('" << stateName << "')." << endl;
219        }
220
221        // Create a factory to delay GameState creation
222        GameStateFactory::createFactory<T>(className);
223
224        // just a required dummy return value
225        return true;
226    }
227} //tolua_export
228
229#endif /* _Game_H__ */
Note: See TracBrowser for help on using the repository browser.