Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Jun 28, 2009, 6:22:40 PM (15 years ago)
Author:
rgrieder
Message:

Moved GameState construction from pre-main() to after Core creation. That makes it possible to use Core features (like configValues) in the GameState constructor.

Location:
code/branches/core4/src/core
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • code/branches/core4/src/core/CorePrereqs.h

    r3196 r3243  
    165165    // game states
    166166    class Game;
     167    struct GameStateConstrParams;
    167168    class GameState;
    168169    struct GameStateTreeNode;
  • code/branches/core4/src/core/Game.cc

    r3238 r3243  
    5454    using boost::weak_ptr;
    5555
    56     std::map<std::string, GameState*> Game::allStates_s;
    57     Game* Game::singletonRef_s = 0;
    58 
    5956    static void stop_game()
    6057        { Game::getInstance().stop(); }
    6158    SetConsoleCommandShortcutExternAlias(stop_game, "exit");
    62     // Add an empty gamestate that serves as internal root state
    63     AddGameState(GameState, "emptyRootGameState");
    6459
    6560    struct _CoreExport GameStateTreeNode
     
    6964        std::vector<shared_ptr<GameStateTreeNode> > children_;
    7065    };
     66
     67    std::map<std::string, Game::GameStateInfo> Game::gameStateDeclarations_s;
     68    Game* Game::singletonRef_s = 0;
    7169
    7270    /**
     
    7674    Game::Game(int argc, char** argv)
    7775    {
    78         assert(singletonRef_s == 0);
     76        if (singletonRef_s != 0)
     77        {
     78            COUT(0) << "Error: The Game singleton cannot be recreated! Shutting down." << std::endl;
     79            abort();
     80        }
    7981        singletonRef_s = this;
    8082
    8183        this->bAbort_ = false;
    8284        bChangingState_ = false;
    83         // The empty root state is ALWAYS loaded!
    84         this->rootStateNode_ = shared_ptr<GameStateTreeNode>(new GameStateTreeNode());
    85         this->rootStateNode_->state_ = getState("emptyRootGameState");
    86         this->activeStateNode_ = this->rootStateNode_;
    87         this->activeStates_.push_back(this->rootStateNode_->state_);
     85
     86        // Create an empty root state
     87        declareGameState<GameState>("GameState", "emptyRootGameState", true, false);
    8888
    8989        // reset statistics
     
    9898        this->gameClock_ = new Clock();
    9999
     100        // Create the Core
    100101        this->core_ = new orxonox::Core();
    101102        this->core_->initialise(argc, argv);
    102103
     104        // After the core has been created, we can safely instantiate the GameStates
     105        for (std::map<std::string, GameStateInfo>::const_iterator it = gameStateDeclarations_s.begin();
     106            it != gameStateDeclarations_s.end(); ++it)
     107        {
     108            // Only create the states appropriate for the game mode
     109            //if (GameMode::showsGraphics || !it->second.bGraphicsMode)
     110            GameStateConstrParams params = { it->second.stateName, it->second.bIgnoreTickTime };
     111            gameStates_[getLowercase(it->second.stateName)] = GameStateFactory::fabricate(it->second.className, params);
     112        }
     113
     114        // The empty root state is ALWAYS loaded!
     115        this->rootStateNode_ = shared_ptr<GameStateTreeNode>(new GameStateTreeNode());
     116        this->rootStateNode_->state_ = getState("emptyRootGameState");
     117        this->activeStateNode_ = this->rootStateNode_;
     118        this->activeStates_.push_back(this->rootStateNode_->state_);
     119
     120        // Do this after Core creation!
    103121        RegisterRootObject(Game);
    104122        this->setConfigValues();
     
    110128    Game::~Game()
    111129    {
    112         // Destroy pretty much everyhting left
     130        // Destroy the GameStates (note that the nodes still point to them, but doesn't matter)
     131        for (std::map<std::string, GameState*>::const_iterator it = gameStates_.begin();
     132            it != gameStates_.end(); ++it)
     133            delete it->second;
     134
     135        // Destroy the Core and with it almost everything
    113136        delete this->core_;
    114 
    115137        delete this->gameClock_;
    116138
    117         assert(singletonRef_s);
    118         singletonRef_s = 0;
     139        // Also, take care of the GameStateFactories
     140        GameStateFactory::destroyFactories();
     141
     142        // Don't assign singletonRef_s with NULL! Recreation is not supported
    119143    }
    120144
     
    165189
    166190            // STATISTICS
    167             statisticsTickInfo tickInfo = {currentTime, 0};
     191            StatisticsTickInfo tickInfo = {currentTime, 0};
    168192            statisticsTickTimes_.push_back(tickInfo);
    169193            this->periodTime_ += this->gameClock_->getDeltaTimeMicroseconds();
     
    240264            if (this->periodTime_ > statisticsRefreshCycle_)
    241265            {
    242                 std::list<statisticsTickInfo>::iterator it = this->statisticsTickTimes_.begin();
     266                std::list<StatisticsTickInfo>::iterator it = this->statisticsTickTimes_.begin();
    243267                assert(it != this->statisticsTickTimes_.end());
    244268                int64_t lastTime = currentTime - this->statisticsAvgLength_;
     
    356380    GameState* Game::getState(const std::string& name)
    357381    {
    358         std::map<std::string, GameState*>::const_iterator it = allStates_s.find(getLowercase(name));
    359         if (it != allStates_s.end())
     382        std::map<std::string, GameState*>::const_iterator it = gameStates_.find(getLowercase(name));
     383        if (it != gameStates_.end())
    360384            return it->second;
    361385        else
     
    448472    }
    449473
    450     /*static*/ bool Game::addGameState(GameState* state)
    451     {
    452         std::map<std::string, GameState*>::const_iterator it = allStates_s.find(getLowercase(state->getName()));
    453         if (it == allStates_s.end())
    454             allStates_s[getLowercase(state->getName())] = state;
    455         else
    456             ThrowException(GameState, "Cannot add two GameStates with the same name to 'Game'.");
    457 
    458         // just a required dummy return value
    459         return true;
    460     }
    461 
    462     /*static*/ void Game::destroyStates()
    463     {
    464         // Delete all GameStates created by the macros
    465         for (std::map<std::string, GameState*>::const_iterator it = allStates_s.begin(); it != allStates_s.end(); ++it)
     474    std::map<std::string, Game::GameStateFactory*> Game::GameStateFactory::factories_s;
     475
     476    /*static*/ GameState* Game::GameStateFactory::fabricate(const std::string& className, const GameStateConstrParams& params)
     477    {
     478        std::map<std::string, GameStateFactory*>::const_iterator it = factories_s.find(className);
     479        assert(it != factories_s.end());
     480        return it->second->fabricate(params);
     481    }
     482
     483    /*static*/ void Game::GameStateFactory::destroyFactories()
     484    {
     485        for (std::map<std::string, GameStateFactory*>::const_iterator it = factories_s.begin(); it != factories_s.end(); ++it)
    466486            delete it->second;
    467         allStates_s.clear();
     487        factories_s.clear();
    468488    }
    469489}
  • code/branches/core4/src/core/Game.h

    r3238 r3243  
    4646#include <boost/preprocessor/cat.hpp>
    4747
     48#include "util/Debug.h"
    4849#include "OrxonoxClass.h"
    4950
     
    5354    and every following paramter is a constructor argument (which is usually non existent)
    5455*/
    55 #define AddGameState(classname, ...) \
    56     static bool BOOST_PP_CAT(bGameStateDummy_##classname, __LINE__) = orxonox::Game::addGameState(new classname(__VA_ARGS__))
     56#define DeclareGameState(className, stateName, bIgnoreTickTime, bGraphicsMode) \
     57    static bool BOOST_PP_CAT(bGameStateDummy_##className, __LINE__) = orxonox::Game::declareGameState<className>(#className, stateName, bIgnoreTickTime, bGraphicsMode)
    5758
    5859// tolua_begin
     
    9192        void addTickTime(uint32_t length);
    9293
    93         static bool addGameState(GameState* state);
    94         static void destroyStates();
     94        template <class T>
     95        static bool declareGameState(const std::string& className, const std::string& stateName, bool bIgnoreTickTime, bool bConsoleMode);
    9596        static Game& getInstance() { assert(singletonRef_s); return *singletonRef_s; } //tolua_export
    9697
     
    99100
    100101    private:
    101         struct statisticsTickInfo
     102        class _CoreExport GameStateFactory
     103        {
     104        public:
     105            virtual ~GameStateFactory() { }
     106            static GameState* fabricate(const std::string& className, const GameStateConstrParams& params);
     107            template <class T>
     108            static void createFactory(const std::string& className)
     109                { factories_s[className] = new TemplateGameStateFactory<T>(); }
     110            static void destroyFactories();
     111        private:
     112            virtual GameState* fabricate(const GameStateConstrParams& params) = 0;
     113            static std::map<std::string, GameStateFactory*> factories_s;
     114        };
     115        template <class T>
     116        class TemplateGameStateFactory : public GameStateFactory
     117        {
     118        public:
     119            GameState* fabricate(const GameStateConstrParams& params)
     120                { return new T(params); }
     121        };
     122
     123        struct GameStateInfo
     124        {
     125            std::string stateName;
     126            std::string className;
     127            bool bIgnoreTickTime;
     128            bool bGraphicsMode;
     129        };
     130
     131        struct StatisticsTickInfo
    102132        {
    103133            uint64_t    tickTime;
     
    110140        void unloadState(GameState* state);
    111141
    112         std::vector<GameState*>         activeStates_;
     142        std::map<std::string, GameState*>    gameStates_;
     143        std::vector<GameState*>              activeStates_;
    113144        boost::shared_ptr<GameStateTreeNode> rootStateNode_;
    114145        boost::shared_ptr<GameStateTreeNode> activeStateNode_;
     
    123154        // variables for time statistics
    124155        uint64_t                        statisticsStartTime_;
    125         std::list<statisticsTickInfo>   statisticsTickTimes_;
     156        std::list<StatisticsTickInfo>   statisticsTickTimes_;
    126157        uint32_t                        periodTime_;
    127158        uint32_t                        periodTickTime_;
     
    134165        std::string                     levelName_;
    135166
    136         static std::map<std::string, GameState*> allStates_s;
     167        static std::map<std::string, GameStateInfo> gameStateDeclarations_s;
    137168        static Game* singletonRef_s;        //!< Pointer to the Singleton
    138         // tolua_begin
    139     };
    140 }
    141 //tolua_end
     169    }; // tolua_export
     170
     171    template <class T>
     172    /*static*/ bool Game::declareGameState(const std::string& className, const std::string& stateName, bool bIgnoreTickTime, bool bGraphicsMode)
     173    {
     174        std::map<std::string, GameStateInfo>::const_iterator it = gameStateDeclarations_s.find(getLowercase(stateName));
     175        if (it == gameStateDeclarations_s.end())
     176        {
     177            GameStateInfo& info = gameStateDeclarations_s[getLowercase(stateName)];
     178            info.stateName = stateName;
     179            info.className = className;
     180            info.bIgnoreTickTime = bIgnoreTickTime;
     181            info.bGraphicsMode = bGraphicsMode;
     182        }
     183        else
     184        {
     185            COUT(0) << "Error: Cannot declare two GameStates with the same name." << std::endl;
     186            COUT(0) << "       Ignoring second one ('" << stateName << "')." << std::endl;
     187        }
     188
     189        // Create a factory to delay GameState creation
     190        GameStateFactory::createFactory<T>(className);
     191
     192        // just a required dummy return value
     193        return true;
     194    }
     195} // tolua_export
     196
    142197#endif /* _Game_H__ */
  • code/branches/core4/src/core/GameState.cc

    r3238 r3243  
    4545        Constructor only initialises variables and sets the name permanently.
    4646    */
    47     GameState::GameState(const std::string& name, bool ignoreTickTime)
    48         : name_(name)
    49         , bIgnoreTickTime_(ignoreTickTime)
     47    GameState::GameState(const GameStateConstrParams& params)
     48        : name_(params.name)
     49        , bIgnoreTickTime_(params.bIgnoreTickTime)
    5050        , parent_(0)
    5151    {
  • code/branches/core4/src/core/GameState.h

    r3238 r3243  
    4545    /**
    4646    @brief
     47        Helper class to group construction parameters for better genericity.
     48    */
     49    struct GameStateConstrParams
     50    {
     51        std::string name;
     52        bool bIgnoreTickTime;
     53    };
     54
     55    /**
     56    @brief
    4757        An implementation of a tree to manage game states.
    4858        This leads to a certain hierarchy that is created at runtime.
     
    7787
    7888    public:
    79         GameState(const std::string& name, bool ignoreTicktime = false);
     89        GameState(const GameStateConstrParams& params);
    8090        virtual ~GameState();
    8191
Note: See TracChangeset for help on using the changeset viewer.