# HG changeset patch # User David Demelier # Date 1618152094 -7200 # Node ID 648f5f949afbe70ade9d611003531d916c6e7e40 # Parent 196264679079c45b808f49c3a996cf2ffa850997 core: implement stackable states diff -r 196264679079 -r 648f5f949afb libmlk-adventure/adventure/action/spawner.c --- a/libmlk-adventure/adventure/action/spawner.c Wed Mar 10 18:49:08 2021 +0100 +++ b/libmlk-adventure/adventure/action/spawner.c Sun Apr 11 16:41:34 2021 +0200 @@ -46,9 +46,8 @@ } static void -fight(void) +fight(struct spawner *s) { - /* TODO: */ struct battle *bt; bt = alloc_new0(sizeof (*bt)); @@ -87,8 +86,8 @@ s->last_y = s->map->player_y; if (s->steps == 0) { - s->steps = util_nrand(s->low, s->high); - fight(); + spawner_init(s); + fight(s); } } diff -r 196264679079 -r 648f5f949afb libmlk-adventure/adventure/molko.c --- a/libmlk-adventure/adventure/molko.c Wed Mar 10 18:49:08 2021 +0100 +++ b/libmlk-adventure/adventure/molko.c Sun Apr 11 16:41:34 2021 +0200 @@ -85,7 +85,7 @@ assets_init(); /* Start to splash. */ - game_switch(state_mainmenu_new(), 1); + game_push(state_mainmenu_new()); molko.team.members[0] = &character_neth; molko.team.members[1] = &character_neth; inventory_add(&molko.inventory, &item_potion, 100); @@ -108,7 +108,7 @@ for (union event ev; event_poll(&ev); ) continue; - game_switch(molko.panic, 1); + game_push(molko.panic); game_loop(); } } @@ -118,7 +118,7 @@ { molko.state = MOLKO_STATE_MAP; - game_switch(state_map_new(map, origin_x, origin_y), 0); + game_push(state_map_new(map, origin_x, origin_y)); game.inhibit = INHIBIT_NONE; } @@ -127,7 +127,7 @@ { molko.state = MOLKO_STATE_BATTLE; - game_switch(state_battle_new(bt), 0); + game_push(state_battle_new(bt)); } const char * diff -r 196264679079 -r 648f5f949afb libmlk-adventure/adventure/state/battle.c --- a/libmlk-adventure/adventure/state/battle.c Wed Mar 10 18:49:08 2021 +0100 +++ b/libmlk-adventure/adventure/state/battle.c Sun Apr 11 16:41:34 2021 +0200 @@ -56,7 +56,7 @@ /* TODO: once we have stacked states, pop it. */ if (battle_update(self->battle, ticks)) - game_quit(); + game_pop(); } static void diff -r 196264679079 -r 648f5f949afb libmlk-adventure/adventure/state/continue.c --- a/libmlk-adventure/adventure/state/continue.c Wed Mar 10 18:49:08 2021 +0100 +++ b/libmlk-adventure/adventure/state/continue.c Sun Apr 11 16:41:34 2021 +0200 @@ -52,7 +52,7 @@ break; case EVENT_KEYDOWN: if (ev->key.key == KEY_ESCAPE) - game_switch(state_mainmenu_new(), 0); + game_push(state_mainmenu_new()); else selected = dialog_save_handle(&self->dialog, ev); break; diff -r 196264679079 -r 648f5f949afb libmlk-adventure/adventure/state/mainmenu.c --- a/libmlk-adventure/adventure/state/mainmenu.c Wed Mar 10 18:49:08 2021 +0100 +++ b/libmlk-adventure/adventure/state/mainmenu.c Sun Apr 11 16:41:34 2021 +0200 @@ -76,7 +76,7 @@ static void resume(void) { - game_switch(state_continue_new(), 0); + game_push(state_continue_new()); } static void diff -r 196264679079 -r 648f5f949afb libmlk-adventure/adventure/state/map.c --- a/libmlk-adventure/adventure/state/map.c Wed Mar 10 18:49:08 2021 +0100 +++ b/libmlk-adventure/adventure/state/map.c Sun Apr 11 16:41:34 2021 +0200 @@ -106,6 +106,14 @@ } static void +suspend(struct state *state) +{ + struct self *self = state->data; + + self->map.player_movement = 0; +} + +static void finish(struct state *state) { struct self *self = state->data; @@ -134,6 +142,7 @@ self->state.handle = handle; self->state.update = update; self->state.draw = draw; + self->state.suspend = suspend; self->state.finish = finish; return &self->state; diff -r 196264679079 -r 648f5f949afb libmlk-adventure/adventure/state/splashscreen.c --- a/libmlk-adventure/adventure/state/splashscreen.c Wed Mar 10 18:49:08 2021 +0100 +++ b/libmlk-adventure/adventure/state/splashscreen.c Sun Apr 11 16:41:34 2021 +0200 @@ -75,7 +75,7 @@ self->elapsed += ticks; if (self->elapsed >= DELAY) - game_switch(state_mainmenu_new(), 0); + game_push(state_mainmenu_new()); } static void diff -r 196264679079 -r 648f5f949afb libmlk-core/core/game.c --- a/libmlk-core/core/game.c Wed Mar 10 18:49:08 2021 +0100 +++ b/libmlk-core/core/game.c Sun Apr 11 16:41:34 2021 +0200 @@ -28,41 +28,34 @@ #include "util.h" #include "window.h" -struct game game; +struct game game = { + .state = &game.states[0], +}; void -game_switch(struct state *state, int quick) +game_push(struct state *state) { assert(state); - - if (quick) { - if (game.state_next) { - state_finish(game.state_next); - game.state_next = NULL; - } + assert(game.state != &game.states[GAME_STATE_MAX]); - if (game.state) { - state_end(game.state); - state_finish(game.state); - } - - state_start(game.state = state); + if (*game.state) { + state_suspend(*game.state); + state_start(*(++game.state) = state); } else - game.state_next = state; + state_start((*game.state) = state); } -struct state * -game_replace(struct state *state) +void +game_pop(void) { - assert(state); + if (!*game.state) + return; - struct state *save = game.state; - - game.state = state; + state_end(*game.state); + state_finish(*game.state); - state_start(state); - - return save; + if (game.state != &game.states[0]) + state_resume(*--game.state); } void @@ -70,48 +63,22 @@ { assert(ev); - if (game.state && !(game.inhibit & INHIBIT_STATE_INPUT)) - state_handle(game.state, ev); + if (*game.state && !(game.inhibit & INHIBIT_STATE_INPUT)) + state_handle(*game.state, ev); } void game_update(unsigned int ticks) { - if (game.inhibit & INHIBIT_STATE_UPDATE) - return; - - /* Change state if any. */ - if (game.state_next) { - struct state *previous; - - /* Inform the current state we're gonna leave it. */ - if ((previous = game.state)) - state_end(previous); - - /* Change the state and tell we're starting it. */ - if ((game.state = game.state_next)) { - game.state_next = NULL; - state_start(game.state); - } - - /* - * Only call finish at the end of the process because - * the user may still use resources from it during the - * transition. - */ - if (previous) - state_finish(previous); - } - - if (game.state) - state_update(game.state, ticks); + if (*game.state && !(game.inhibit & INHIBIT_STATE_UPDATE)) + state_update(*game.state, ticks); } void game_draw(void) { if (game.state && !(game.inhibit & INHIBIT_STATE_DRAW)) - state_draw(game.state); + state_draw(*game.state); } void @@ -150,15 +117,5 @@ void game_quit(void) { - /* Close the next state if any. */ - if (game.state_next) { - state_finish(game.state_next); - game.state_next = NULL; - } - - if (game.state) { - state_end(game.state); - state_finish(game.state); - game.state = NULL; - } + // TODO: clear. } diff -r 196264679079 -r 648f5f949afb libmlk-core/core/game.h --- a/libmlk-core/core/game.h Wed Mar 10 18:49:08 2021 +0100 +++ b/libmlk-core/core/game.h Sun Apr 11 16:41:34 2021 +0200 @@ -22,17 +22,16 @@ #include "core.h" #include "inhibit.h" +#define GAME_STATE_MAX (32) + struct state; union event; struct game { - /* Inhibition */ enum inhibit inhibit; - - /* Game states. */ - struct state *state; - struct state *state_next; + struct state *states[GAME_STATE_MAX + 1]; + struct state **state; }; extern struct game game; @@ -40,10 +39,10 @@ CORE_BEGIN_DECLS void -game_switch(struct state *, int); +game_push(struct state *); -struct state * -game_replace(struct state *); +void +game_pop(void); void game_handle(const union event *); diff -r 196264679079 -r 648f5f949afb libmlk-core/core/state.c --- a/libmlk-core/core/state.c Wed Mar 10 18:49:08 2021 +0100 +++ b/libmlk-core/core/state.c Sun Apr 11 16:41:34 2021 +0200 @@ -58,6 +58,24 @@ } void +state_suspend(struct state *state) +{ + assert(state); + + if (state->suspend) + state->suspend(state); +} + +void +state_resume(struct state *state) +{ + assert(state); + + if (state->resume) + state->resume(state); +} + +void state_end(struct state *state) { assert(state); diff -r 196264679079 -r 648f5f949afb libmlk-core/core/state.h --- a/libmlk-core/core/state.h Wed Mar 10 18:49:08 2021 +0100 +++ b/libmlk-core/core/state.h Sun Apr 11 16:41:34 2021 +0200 @@ -29,6 +29,8 @@ void (*handle)(struct state *, const union event *); void (*update)(struct state *, unsigned int); void (*draw)(struct state *); + void (*suspend)(struct state *); + void (*resume)(struct state *); void (*end)(struct state *); void (*finish)(struct state *); }; @@ -48,6 +50,12 @@ state_draw(struct state *); void +state_suspend(struct state *); + +void +state_resume(struct state *); + +void state_end(struct state *); void diff -r 196264679079 -r 648f5f949afb libmlk-data/maps/map-world.json --- a/libmlk-data/maps/map-world.json Wed Mar 10 18:49:08 2021 +0100 +++ b/libmlk-data/maps/map-world.json Sun Apr 11 16:41:34 2021 +0200 @@ -63,7 +63,7 @@ { "name":"exec", "type":"string", - "value":"spawner|1|2" + "value":"spawner|1000|2000" }], "rotation":0, "type":"", @@ -109,4 +109,4 @@ "type":"map", "version":1.4, "width":300 -} \ No newline at end of file +}