How do I manage game states?

Good day fellas (Me). Today I will show you how to set a game state manager in C. First define your State struct:

typedef struct{
    void (*on_enter)(void*data);
    void (*on_exit)(void*data);
    void (*update)(void*data, float dt);
    void (*render)(void*data);
    void *instance_data;
}State;

As you can see in State struct it’s all function pointers, instace_data points to the specific data for each different state, you just have to cast it inside your function as show below:

typedef struct{
    int data;
}GameplayData;

// example!!!
static void gameplay_on_enter(void *data){
    GameplayData *gp = (GameplayData*)data;
    // make it work
    int id = gp->ecs.create_entity();
};

static void gameplay_on_exit(void *data){};
static void gameplay_update(void *data, float dt){};
static void gameplay_render(void *data){};

State make_gameplay_state(GameplayData *data);

so you can have a gameplay_state / pause_state / ui_state and use a state manager to juggle with then:

#ifndef STATE_STACK_MANAGER_H
#define STATE_STACK_MANAGER_H

#include "state.h"

#define MAX_STATES 10

typedef struct{
    State *stack[MAX_STATES];
    int top;
}StateStackManager;

void state_stack_init(StateStackManager *self);
void state_stack_push(StateStackManager *self, State *state);
State *state_stack_pop(StateStackManager *self);

#endif // STATE_STACK_MANAGER_H

now the definitions:

C
#include "state_stack_manager.h"

void state_stack_init(StateStackManager *self){
    self->top = -1;

    // make sure all is clear (I should use memset lol)
    for (int i = 0; i < MAX_STATES; ++i) {
        self->stack[0] = NULL;
    }
}

void state_stack_push(StateStackManager *self, State *state){
    if(self->top < MAX_STATES -1){
        self->stack[++self->top] = state;
        if(state->on_enter) state->on_enter(state->instance_data);
    }
}

State *state_stack_pop(StateStackManager *self){
    if(self->top >= 0){
        State *state = self->stack[self->top];

        if(state->on_exit){
            state->on_exit(state->instance_data);
            self->top--;
            return state;
        }
    }
    return NULL;
}

After that you just have to put it inside your game loop!

Have fun…

Leave a Reply

Your email address will not be published. Required fields are marked *