Game State Management using Lua

Fishcake
  • Game State Management using Lua Fishcake

    I want to be able to (only) define game states using Lua script, but I'm not sure how I should do it. Here's what I have in mind currently:

    For each state, I will create a .lua file that contains a class (table) that has the same name as the file name. Each table must have a set of event handlers: onEnter (called when the state is entered), onUpdate (called every frame) and onExit (called when exiting the state). So if I want to have a MainMenuState, I will have a file called "MainMenuState.lua" which will contain something like this:

    MainMenuState = {}
    
    MainMenuState["onEnter"] = function()
    end
    
    MainMenuState["onUpdate"] = function(elapsedTime)
    end
    
    MainMenuState["onExit"] = function()
    end
    

    Defined states will be exposed to the game engine via a singleton StateManager class. StateManager will have a function that registers a state under a unique name:

    void registerState(string stateName, string fileName);
    

    State registration will be done in script by placing the registration codes inside an init script that is called once after the game engine is initialized:

    --init.lua
    --Register all the states needed by the game
    StateManager:registerState("SplashScreen", "SplashScreen.lua")
    StateManager:registerState("MainMenuState", "MainMenuState.lua")
    StateManager:registerState("InGameState", "InGameState.lua")
    -- etc etc
    

    StateManager will also keep track of which state is currently active and also handle state transitions:

    //cpp
    void changeState(string state);
    
    --lua
    StateManager:changeState("PauseMenuState")
    

  • It's not entirely clear what you're asking, but there's nothing inherently "wrong" with the way you are structuring your state machine. As long as it fits the task at hand, any implementation can be considered "correct".

    One change I would suggest making is to allow the states themselves to be instanced, so that you can store state in your instance. This can be as simple as:

    SplashScreen = {}
    local instance = setmetatable({}, SplashScreen)
    
    SplashScreen.createInstance = function(...)
        local instance = setmetatable({}, SplashScreen)
        instance.endTime = 5.0 -- set instance data
        return instance
    end
    
    function SplashScreen:update(elapsedTime)
        if elapsedTime > self.endTime then -- use instance data
            changeState('MainMenuState')
        end
    end
    

    Note that, due to the setmetatable call, instance tracks all of your state's functions; so your 'current state' is really just an instance ref in your StateManager:

    function StateManager:changeState(stateName, ...)
        local stateTable = --[[ get state from file ]]
        local instance = stateTable.createInstance(...)
    
        self.currentState = instance
    end
    
    function StateManager:call(funcName, ...)
        local fn = self.currentState[funcName]
        fn(self.currentState, ...)
    end
    

  • I preferred to use numbers with my state systems. It's not the best way but it works great for me.

    state = 1
    while true do
        if state==1 then
           if 1=1 then
              state=2
           end
        end
        if state==2 then
            if 2=2 then
              state=1
            end 
        end
    end
    

    works for me :)

Tags
c++ scripting state lua
Related questions and answers
  • in the main function * not Finally.. but i believe that te numb_coll problem has something to do with the time and framrate. When running full speed i quickly die upon entering a wall as numb_coll... /////////////////////////////////////////////////////////////////////////////////////////////////////////////// class Sprite { private: string name; char symbol; float shield; int location[2]; bool alive; public: ///////////////////// Get and SET all the privates... destroy_shield() {shield--; if(shield<0) alive= false;} string get_name() {return name;}; string set_name(string aName) {name = aName;}; int* get_location(){return location;}; void

  • I've decided I want to write a central ResourceManager/ResourceCache class for my hobby game engine, but am having trouble designing a caching scheme. The idea is that the ResourceManager has a soft target for the total memory used by all the game's resources combined. Other classes will create resource objects, which will be in an unloaded state, and pass them to the ResourceManager... using a string id or a unique identifier). If the resource is loaded, then a read-only reference to the resource is passed to the calling function, (wrapped in a referenced counted weak_ptr

  • different objects in my game: plane, obstacle, player, bullet and I designed them like this: class Player : public GlObject{ private: std::string name; public: Player(); Bullet fire() const; //this method is unique to the class player void generate_mesh(); } Now in the game engine I want to have a general object list where I can check for example for collision, move objects, and so on, but I want also that the game engine will take the user commands to control the player... Is this a good Idea? class GameEngine{ private: std::vector<GlObject*> objects; //an array

  • this on what I had done there, but modifying it to fit with Ogre. It is working but not correctly and I would like some help to understand what it is I am doing wrong. I have a state system and when... code shows the changes I made to get accurate physics. void GameState::createScene() { m_pSceneMgr->createLight("Light")->setPosition(75,75,75); // Physics // As a test we want a floor plane... *) (node)); // Add it to the physics world World->addRigidBody(RigidBody); Objects.push_back(RigidBody); m_pNumEntities++; // End Physics } I then have a method to create a cube and give it rigid body

  • using the boost library extensively and have been using SFML for graphics and FMOD for audio. I have a fair bit of code written, but am considering scrapping it and starting over. Here's the major areas of concern I have and wanted to get some opinions on the proper way others have solved them or would solve them. 1. Cyclical Dependencies When I was doing the game in C#, I didn't really have... my classes and still have them do what I want. Here's a few examples of a dependency chain: I have a status effect class. The class has a number of methods (Apply/Unapply, Tick, etc.) to apply

  • ) is therefore highly wasteful. Then again, making each entity state a singleton hardly seems appropriate. What do you suggest I do? (The same can be said about game states, so whatever the solution to this is, I guess it can be applied to game states as well.) 2. The state of the entity sprite. Most of the time, whenever the state of the entity changes, the sprite that is used to represent it must... work. 1. I noticed entity states are... well, stateless. Basically, they just act on the data in the entity accordingly, they hold no data of their own. When an entity forwards events to its states

  • I'm developing some algorithms in Lua which are run mostly in Lua (few calls to C++) and I'm noticing a huge slowdown when I'm running them from my app rather than the default Lua interpreter. The script returns in about 11 seconds with the interpreter, and about 5+ minutes with my program. I don't think it is a problem with calling the C++ function, overruling that function with an empty function in the script has no noticeable effect for time. Both Lua and the program are compiled with Visual Studio 2010 (I created a new solution for Lua, with projects for both the interpreter and static

  • I have got some problem implementing bullet physics into my opengl game. The thing is that it doesn't want to update my translatef value continously but only at the end. The code for bullet looks...( STATE_FALL_BALL ); printf("stoped\n"); } And the drawing function which is called at the beginning looks like this: void CGL::fallingBall( void ) { glPushMatrix(); float colBall2[4] = { 0.0f, 0.0f... is that it shows correct value in this function's printf but translation is called only at the beginning I mean I can only see the last state. Can anyone help me, please?

  • Basically when placed in the same file this works fine, but if placed in separate files (and I have tested this) just after Init() is called, the pointer to ID3D10* device's value is suddenly...(); }; #endif If I call Init() from game.cpp, the code works fine, if I call cube->init(), just as this function is entered (not when the other one is left), the device pointer suddenly has an address...() { } Cube::~Cube() { pBuffer->Release(); // why does this only work when put here? because it's created here? I thnk so, why not iBuffer though? } void Cube::Draw() { render_frame(); } void Cube

Data information