feat(state machine): state machine now no longer has a separate next function

instead update is expected to return the next state
This commit is contained in:
Sara 2023-11-22 13:02:21 +01:00 committed by Scott-G-GD
parent fd0183d34a
commit 7a0a60846a
3 changed files with 22 additions and 24 deletions

View file

@ -8,23 +8,20 @@ typedef struct State State;
struct State { struct State {
void (*const enter)(void* data); void (*const enter)(void* data);
void (*const exit)(void* data); void (*const exit)(void* data);
void (*const update)(void* data, float dt); const State* (*const update)(void* data, float dt);
const State* (*const next)(void* data);
}; };
#define DefineState(_StateName, enter_fn, exit_fn, update_fn, next_fn)\ #define DefineState(_StateName, enter_fn, exit_fn, update_fn)\
static inline const State* _StateName() {\ static inline const State* _StateName() {\
TC_FN_TYPECHECK(void, enter_fn, void*);\ TC_FN_TYPECHECK(void, enter_fn, void*);\
TC_FN_TYPECHECK(void, exit_fn, void*);\ TC_FN_TYPECHECK(void, exit_fn, void*);\
TC_FN_TYPECHECK(void, update_fn, void*, float);\ TC_FN_TYPECHECK(const State*, update_fn, void*, float);\
TC_FN_TYPECHECK(const State*, next_fn, void*);\
static const State instance = {\ static const State instance = {\
.enter = (void(*const)(void*)) enter_fn,\ .enter = (void(*const)(void*)) enter_fn,\
.exit = (void(*const)(void*)) exit_fn,\ .exit = (void(*const)(void*)) exit_fn,\
.update = (void(*const)(void*, float)) update_fn,\ .update = (const State*(*const)(void*, float)) update_fn,\
.next = (const State*(*const)(void*)) next_fn\
};\ };\
return instance;\ return &instance;\
}\ }\
#endif // !_fencer_state_h #endif // !_fencer_state_h

View file

@ -1,20 +1,29 @@
#include "state_machine.h" #include "state_machine.h"
#include "stdlib.h" #include "stdlib.h"
#include "debug.h"
struct StateMachine { struct StateMachine {
const State* current_state; const State* current_state;
void* data; void* data;
}; };
static inline
void internal_state_machine_set_state(StateMachine* self, const State* state) {
self->current_state->exit(self->data);
self->current_state = state;
self->current_state->enter(self->data);
}
StateMachine* state_machine_init(void* data, const State* start_state) { StateMachine* state_machine_init(void* data, const State* start_state) {
StateMachine* self = malloc(sizeof(StateMachine)); StateMachine* self = malloc(sizeof(StateMachine));
ASSERT_RETURN(self != NULL, NULL, "Failed to allocate space for StateMachine instance");
*self = (StateMachine){ *self = (StateMachine){
.current_state = start_state, .current_state = start_state,
.data = data .data = data
}; };
self->current_state->enter(self->data); self->current_state->enter(self->data);
return self; return self;
} }
@ -23,20 +32,12 @@ void state_machine_destroy(StateMachine* self) {
free(self); free(self);
} }
void state_machine_set_state(StateMachine* self, const State* state) { void state_machine_update(StateMachine* self, float dt) {
self->current_state->exit(self->data); const State* next = self->current_state->update(self->data, dt);
self->current_state = state; if(next != self->current_state)
self->current_state->enter(self->data); internal_state_machine_set_state(self, next);
} }
const State* state_machine_get_state(StateMachine* self) { const State* state_machine_get_current_state(StateMachine* self) {
return self->current_state; return self->current_state;
} }
void state_machine_update(StateMachine* self, float dt) {
self->current_state->update(self->data, dt);
const State* next = self->current_state->next(self->data);
if(next != self->current_state)
state_machine_set_state(self, next);
}

View file

@ -8,8 +8,8 @@ typedef struct StateMachine StateMachine;
extern StateMachine* state_machine_init(void* data, const State* start_state); extern StateMachine* state_machine_init(void* data, const State* start_state);
extern void state_machine_destroy(StateMachine* self); extern void state_machine_destroy(StateMachine* self);
extern void state_machine_set_state(StateMachine* self, const State* state);
extern const State* state_machine_get_current_state(StateMachine* self);
extern void state_machine_update(StateMachine* self, float dt); extern void state_machine_update(StateMachine* self, float dt);
extern const State* state_machine_get_current_state(StateMachine* self);
#endif // !_fencer_state_machine_h #endif // !_fencer_state_machine_h