Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/libraries/core/Game.h @ 7266

Last change on this file since 7266 was 7266, checked in by rgrieder, 14 years ago

Moved Loki library files to separate loki folder in externals.
Also added TypeManip.h (now used in Convert.h) and static_check.h.

  • Property svn:eol-style set to native
File size: 7.8 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@brief
32    Declaration of Game Singleton.
33 */
34
35#ifndef _Game_H__
36#define _Game_H__
37
38#include "CorePrereqs.h"
39
40#include <cassert>
41#include <list>
42#include <map>
43#include <string>
44#include <vector>
45#include <boost/shared_ptr.hpp>
46#include <boost/scoped_ptr.hpp>
47#include <boost/preprocessor/cat.hpp>
48#include <loki/ScopeGuard.h>
49
50#include "util/Debug.h"
51#include "util/Singleton.h"
52#include "OrxonoxClass.h"
53
54/**
55@def
56    Adds a new GameState to the Game. The second parameter is the name as string
57    and every following paramter 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, __LINE__) = 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 OrxonoxClass
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        ~Game();
94
95        void setConfigValues();
96
97        void setStateHierarchy(const std::string& str);
98        shared_ptr<GameState> getState(const std::string& name);
99
100        void run();
101        void stop();
102
103        static Game& getInstance(){ return Singleton<Game>::getInstance(); } // tolua_export
104
105        void requestState(const std::string& name); //tolua_export
106        void requestStates(const std::string& names); //tolua_export
107        void popState(); //tolua_export
108
109        const Clock& getGameClock() { return *this->gameClock_; }
110
111        float getAvgTickTime() { return this->avgTickTime_; }
112        float getAvgFPS()      { return this->avgFPS_; }
113
114        void subtractTickTime(int32_t length);
115
116        template <class T>
117        static bool declareGameState(const std::string& className, const std::string& stateName, bool bIgnoreTickTime, bool bConsoleMode);
118
119    private:
120        class _CoreExport GameStateFactory
121        {
122        public:
123            virtual ~GameStateFactory() { }
124            static shared_ptr<GameState> fabricate(const GameStateInfo& info);
125            template <class T>
126            static void createFactory(const std::string& className)
127                { getFactories()[className].reset(new TemplateGameStateFactory<T>()); }
128
129            virtual shared_ptr<GameState> fabricateInternal(const GameStateInfo& info) = 0;
130            static std::map<std::string, shared_ptr<GameStateFactory> >& getFactories();
131        };
132        template <class T>
133        class TemplateGameStateFactory : public GameStateFactory
134        {
135        public:
136            shared_ptr<GameState> fabricateInternal(const GameStateInfo& info)
137                { return shared_ptr<GameState>(new T(info)); }
138        };
139        // For the factory destruction
140        typedef Loki::ObjScopeGuardImpl0<std::map<std::string, shared_ptr<GameStateFactory> >, void (std::map<std::string, shared_ptr<GameStateFactory> >::*)()> ObjScopeGuard;
141
142        struct StatisticsTickInfo
143        {
144            uint64_t    tickTime;
145            uint32_t    tickLength;
146        };
147
148        Game(Game&); // don't mess with singletons
149
150        void loadGraphics();
151        void unloadGraphics();
152
153        void parseStates(std::vector<std::pair<std::string, int> >::const_iterator& it, shared_ptr<GameStateTreeNode> currentNode);
154        bool checkState(const std::string& name) const;
155        void loadState(const std::string& name);
156        void unloadState(const std::string& name);
157
158        // Main loop structuring
159        void updateGameStateStack();
160        void updateGameStates();
161        void updateStatistics();
162        void updateFPSLimiter();
163
164        // ScopeGuard helper function
165        void resetChangingState() { this->bChangingState_ = false; }
166
167        scoped_ptr<Clock>                  gameClock_;
168        scoped_ptr<Core>                   core_;
169        ObjScopeGuard                      gsFactoryDestroyer_;
170
171        GameStateMap                       constructedStates_;
172        GameStateVector                    loadedStates_;
173        GameStateTreeNodePtr               rootStateNode_;
174        GameStateTreeNodePtr               loadedTopStateNode_;
175        std::vector<GameStateTreeNodePtr>  requestedStateNodes_;
176
177        bool                               bChangingState_;
178        bool                               bAbort_;
179
180        // variables for time statistics
181        uint64_t                           statisticsStartTime_;
182        std::list<StatisticsTickInfo>      statisticsTickTimes_;
183        uint32_t                           periodTime_;
184        uint32_t                           periodTickTime_;
185        float                              avgFPS_;
186        float                              avgTickTime_;
187        int                                excessSleepTime_;
188        unsigned int                       minimumSleepTime_;
189
190        // config values
191        unsigned int                       statisticsRefreshCycle_;
192        unsigned int                       statisticsAvgLength_;
193        unsigned int                       fpsLimit_;
194
195        static std::map<std::string, GameStateInfo> gameStateDeclarations_s;
196        static Game* singletonPtr_s;        //!< Pointer to the Singleton
197    }; //tolua_export
198
199    template <class T>
200    /*static*/ bool Game::declareGameState(const std::string& className, const std::string& stateName, bool bIgnoreTickTime, bool bGraphicsMode)
201    {
202        std::map<std::string, GameStateInfo>::const_iterator it = gameStateDeclarations_s.find(stateName);
203        if (it == gameStateDeclarations_s.end())
204        {
205            GameStateInfo& info = gameStateDeclarations_s[stateName];
206            info.stateName = stateName;
207            info.className = className;
208            info.bIgnoreTickTime = bIgnoreTickTime;
209            info.bGraphicsMode = bGraphicsMode;
210        }
211        else
212        {
213            COUT(0) << "Error: Cannot declare two GameStates with the same name." << std::endl;
214            COUT(0) << "       Ignoring second one ('" << stateName << "')." << std::endl;
215        }
216
217        // Create a factory to delay GameState creation
218        GameStateFactory::createFactory<T>(className);
219
220        // just a required dummy return value
221        return true;
222    }
223} //tolua_export
224
225#endif /* _Game_H__ */
Note: See TracBrowser for help on using the repository browser.