Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/steering/src/libraries/core/Game.h @ 6372

Last change on this file since 6372 was 5929, checked in by rgrieder, 15 years ago

Merged core5 branch back to the trunk.
Key features include clean level unloading and an extended XML event system.

Two important notes:
Delete your keybindings.ini files! * or you will still get parser errors when loading the key bindings.
Delete build_dir/lib/modules/libgamestates.module! * or orxonox won't start.
Best thing to do is to delete the build folder ;)

  • Property svn:eol-style set to native
File size: 7.4 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
49#include "util/Debug.h"
50#include "util/ScopeGuard.h"
51#include "util/Singleton.h"
52
53/**
54@def
55    Adds a new GameState to the Game. The second parameter is the name as string
56    and every following paramter is a constructor argument (which is usually non existent)
57*/
58#define DeclareGameState(className, stateName, bIgnoreTickTime, bGraphicsMode) \
59    static bool BOOST_PP_CAT(bGameStateDummy_##className, __LINE__) = orxonox::Game::declareGameState<className>(#className, stateName, bIgnoreTickTime, bGraphicsMode)
60
61namespace orxonox
62{
63    class GameConfiguration;
64
65    //! Helper object required before GameStates are being constructed
66    struct GameStateInfo
67    {
68        std::string stateName;
69        std::string className;
70        bool bIgnoreTickTime;
71        bool bGraphicsMode;
72    };
73
74    /**
75    @brief
76        Main class responsible for running the game.
77    @remark
78        You should only create this singleton once because it owns the Core class! (see remark there)
79    */
80    class _CoreExport Game : public Singleton<Game>
81    {
82        friend class Singleton<Game>;
83        typedef std::vector<shared_ptr<GameState> > GameStateVector;
84        typedef std::map<std::string, shared_ptr<GameState> > GameStateMap;
85        typedef shared_ptr<GameStateTreeNode> GameStateTreeNodePtr;
86
87    public:
88        Game(const std::string& cmdLine);
89        ~Game();
90
91        void setStateHierarchy(const std::string& str);
92        shared_ptr<GameState> getState(const std::string& name);
93
94        void run();
95        void stop();
96
97        void requestState(const std::string& name);
98        void requestStates(const std::string& names);
99        void popState();
100
101        const Clock& getGameClock() { return *this->gameClock_; }
102
103        float getAvgTickTime() { return this->avgTickTime_; }
104        float getAvgFPS()      { return this->avgFPS_; }
105
106        void subtractTickTime(int32_t length);
107
108        template <class T>
109        static bool declareGameState(const std::string& className, const std::string& stateName, bool bIgnoreTickTime, bool bConsoleMode);
110
111    private:
112        class _CoreExport GameStateFactory
113        {
114        public:
115            virtual ~GameStateFactory() { }
116            static shared_ptr<GameState> fabricate(const GameStateInfo& info);
117            template <class T>
118            static void createFactory(const std::string& className)
119                { getFactories()[className].reset(new TemplateGameStateFactory<T>()); }
120
121            virtual shared_ptr<GameState> fabricateInternal(const GameStateInfo& info) = 0;
122            static std::map<std::string, shared_ptr<GameStateFactory> >& getFactories();
123        };
124        template <class T>
125        class TemplateGameStateFactory : public GameStateFactory
126        {
127        public:
128            shared_ptr<GameState> fabricateInternal(const GameStateInfo& info)
129                { return shared_ptr<GameState>(new T(info)); }
130        };
131        // For the factory destruction
132        typedef Loki::ObjScopeGuardImpl0<std::map<std::string, shared_ptr<GameStateFactory> >, void (std::map<std::string, shared_ptr<GameStateFactory> >::*)()> ObjScopeGuard;
133
134        struct StatisticsTickInfo
135        {
136            uint64_t    tickTime;
137            uint32_t    tickLength;
138        };
139
140        Game(Game&); // don't mess with singletons
141
142        void loadGraphics();
143        void unloadGraphics();
144
145        void parseStates(std::vector<std::pair<std::string, int> >::const_iterator& it, shared_ptr<GameStateTreeNode> currentNode);
146        bool checkState(const std::string& name) const;
147        void loadState(const std::string& name);
148        void unloadState(const std::string& name);
149
150        // Main loop structuring
151        void updateGameStateStack();
152        void updateGameStates();
153        void updateStatistics();
154        void updateFPSLimiter();
155
156        // ScopeGuard helper function
157        void resetChangingState() { this->bChangingState_ = false; }
158
159        scoped_ptr<Clock>                  gameClock_;
160        scoped_ptr<Core>                   core_;
161        ObjScopeGuard                      gsFactoryDestroyer_;
162        scoped_ptr<GameConfiguration>      configuration_;
163
164        GameStateMap                       constructedStates_;
165        GameStateVector                    loadedStates_;
166        GameStateTreeNodePtr               rootStateNode_;
167        GameStateTreeNodePtr               loadedTopStateNode_;
168        std::vector<GameStateTreeNodePtr>  requestedStateNodes_;
169
170        bool                               bChangingState_;
171        bool                               bAbort_;
172
173        // variables for time statistics
174        uint64_t                           statisticsStartTime_;
175        std::list<StatisticsTickInfo>      statisticsTickTimes_;
176        uint32_t                           periodTime_;
177        uint32_t                           periodTickTime_;
178        float                              avgFPS_;
179        float                              avgTickTime_;
180        int                                excessSleepTime_;
181        unsigned int                       minimumSleepTime_;
182
183        static std::map<std::string, GameStateInfo> gameStateDeclarations_s;
184        static Game* singletonPtr_s;        //!< Pointer to the Singleton
185    };
186
187    template <class T>
188    /*static*/ bool Game::declareGameState(const std::string& className, const std::string& stateName, bool bIgnoreTickTime, bool bGraphicsMode)
189    {
190        std::map<std::string, GameStateInfo>::const_iterator it = gameStateDeclarations_s.find(stateName);
191        if (it == gameStateDeclarations_s.end())
192        {
193            GameStateInfo& info = gameStateDeclarations_s[stateName];
194            info.stateName = stateName;
195            info.className = className;
196            info.bIgnoreTickTime = bIgnoreTickTime;
197            info.bGraphicsMode = bGraphicsMode;
198        }
199        else
200        {
201            COUT(0) << "Error: Cannot declare two GameStates with the same name." << std::endl;
202            COUT(0) << "       Ignoring second one ('" << stateName << "')." << std::endl;
203        }
204
205        // Create a factory to delay GameState creation
206        GameStateFactory::createFactory<T>(className);
207
208        // just a required dummy return value
209        return true;
210    }
211}
212
213#endif /* _Game_H__ */
Note: See TracBrowser for help on using the repository browser.