diff --git a/src/gamestate.c b/src/gamestate.c index edaa76d..819d057 100644 --- a/src/gamestate.c +++ b/src/gamestate.c @@ -73,6 +73,7 @@ SYMBOL_EXPORT void LoadGamestate(struct Game *game, const char* name) { gs->showLoading = true; } PrintConsole(game, "Gamestate \"%s\" marked to be LOADED.", name); + game->_priv.gamestate_scheduled = true; } SYMBOL_EXPORT void UnloadGamestate(struct Game *game, const char* name) { @@ -93,6 +94,7 @@ SYMBOL_EXPORT void UnloadGamestate(struct Game *game, const char* name) { } else { PrintConsole(game, "Tried to unload nonexisitent gamestate \"%s\"", name); } + game->_priv.gamestate_scheduled = true; } SYMBOL_EXPORT void StartGamestate(struct Game *game, const char* name) { @@ -107,6 +109,7 @@ SYMBOL_EXPORT void StartGamestate(struct Game *game, const char* name) { } else { PrintConsole(game, "Tried to start nonexisitent gamestate \"%s\"", name); } + game->_priv.gamestate_scheduled = true; } SYMBOL_EXPORT void StopGamestate(struct Game *game, const char* name) { @@ -126,6 +129,7 @@ SYMBOL_EXPORT void StopGamestate(struct Game *game, const char* name) { } else { PrintConsole(game, "Tried to stop nonexisitent gamestate \"%s\"", name); } + game->_priv.gamestate_scheduled = true; } SYMBOL_EXPORT void PauseGamestate(struct Game *game, const char* name) { @@ -178,3 +182,7 @@ SYMBOL_EXPORT void SwitchGamestate(struct Game *game, const char* current, const LoadGamestate(game, n); StartGamestate(game, n); } + +SYMBOL_EXPORT void SwitchCurrentGamestate(struct Game *game, const char* n) { + SwitchGamestate(game, game->_priv.current_gamestate->name, n); +} diff --git a/src/gamestate.h b/src/gamestate.h index b006d0d..0bee9e2 100644 --- a/src/gamestate.h +++ b/src/gamestate.h @@ -60,5 +60,6 @@ void PauseGamestate(struct Game *game, const char* name); void ResumeGamestate(struct Game *game, const char* name); void UnloadAllGamestates(struct Game *game); void SwitchGamestate(struct Game *game, const char* current, const char* n); +void SwitchCurrentGamestate(struct Game *game, const char* n); #endif diff --git a/src/internal.c b/src/internal.c index 40546e9..1a54511 100644 --- a/src/internal.c +++ b/src/internal.c @@ -29,6 +29,7 @@ SYMBOL_INTERNAL void DrawGamestates(struct Game *game) { struct Gamestate *tmp = game->_priv.gamestates; while (tmp) { if ((tmp->loaded) && (tmp->started)) { + game->_priv.current_gamestate = tmp; (*tmp->api.Gamestate_Draw)(game, tmp->data); } tmp = tmp->next; @@ -39,6 +40,7 @@ SYMBOL_INTERNAL void LogicGamestates(struct Game *game) { struct Gamestate *tmp = game->_priv.gamestates; while (tmp) { if ((tmp->loaded) && (tmp->started) && (!tmp->paused)) { + game->_priv.current_gamestate = tmp; (*tmp->api.Gamestate_Logic)(game, tmp->data); } tmp = tmp->next; @@ -49,6 +51,7 @@ SYMBOL_INTERNAL void EventGamestates(struct Game *game, ALLEGRO_EVENT *ev) { struct Gamestate *tmp = game->_priv.gamestates; while (tmp) { if ((tmp->loaded) && (tmp->started) && (!tmp->paused)) { + game->_priv.current_gamestate = tmp; (*tmp->api.Gamestate_ProcessEvent)(game, tmp->data, ev); } tmp = tmp->next; @@ -59,6 +62,7 @@ SYMBOL_INTERNAL void PauseGamestates(struct Game *game) { struct Gamestate *tmp = game->_priv.gamestates; while (tmp) { if ((tmp->loaded) && (tmp->started)) { + game->_priv.current_gamestate = tmp; (*tmp->api.Gamestate_Pause)(game, tmp->data); } tmp = tmp->next; @@ -70,6 +74,7 @@ SYMBOL_INTERNAL void ResumeGamestates(struct Game *game) { struct Gamestate *tmp = game->_priv.gamestates; while (tmp) { if ((tmp->loaded) && (tmp->started)) { + game->_priv.current_gamestate = tmp; (*tmp->api.Gamestate_Resume)(game, tmp->data); } tmp = tmp->next; @@ -123,17 +128,17 @@ SYMBOL_INTERNAL void Console_Unload(struct Game *game) { } SYMBOL_INTERNAL void GamestateProgress(struct Game *game) { - struct Gamestate *tmp = game->_priv.cur_gamestate.tmp; - game->_priv.cur_gamestate.p++; + struct Gamestate *tmp = game->_priv.tmp_gamestate.tmp; + game->_priv.tmp_gamestate.p++; DrawGamestates(game); float progressCount = *(tmp->api.Gamestate_ProgressCount) ? (float)*(tmp->api.Gamestate_ProgressCount) : 1; - float progress = ((game->_priv.cur_gamestate.p / progressCount) / (float)game->_priv.cur_gamestate.toLoad) + (game->_priv.cur_gamestate.loaded/(float)game->_priv.cur_gamestate.toLoad); - if (game->config.debug) PrintConsole(game, "[%s] Progress: %d% (%d/%d)", tmp->name, (int)(progress*100), game->_priv.cur_gamestate.p, *(tmp->api.Gamestate_ProgressCount)); + float progress = ((game->_priv.tmp_gamestate.p / progressCount) / (float)game->_priv.tmp_gamestate.toLoad) + (game->_priv.tmp_gamestate.loaded/(float)game->_priv.tmp_gamestate.toLoad); + if (game->config.debug) PrintConsole(game, "[%s] Progress: %d% (%d/%d)", tmp->name, (int)(progress*100), game->_priv.tmp_gamestate.p, *(tmp->api.Gamestate_ProgressCount)); if (tmp->showLoading) (*game->_priv.loading.Draw)(game, game->_priv.loading.data, progress); DrawConsole(game); - if (al_get_time() - game->_priv.cur_gamestate.t >= 1/60.0) { + if (al_get_time() - game->_priv.tmp_gamestate.t >= 1/60.0) { al_flip_display(); - game->_priv.cur_gamestate.t = al_get_time(); + game->_priv.tmp_gamestate.t = al_get_time(); } } diff --git a/src/libsuperderpy.c b/src/libsuperderpy.c index 05ebd32..745f0f1 100644 --- a/src/libsuperderpy.c +++ b/src/libsuperderpy.c @@ -148,6 +148,7 @@ SYMBOL_EXPORT struct Game* libsuperderpy_init(int argc, char** argv, const char* al_set_new_bitmap_flags(ALLEGRO_MIN_LINEAR); game->_priv.gamestates = NULL; + game->_priv.gamestate_scheduled = false; game->_priv.event_queue = al_create_event_queue(); if(!game->_priv.event_queue) { @@ -230,24 +231,26 @@ SYMBOL_EXPORT int libsuperderpy_run(struct Game *game) { while(1) { ALLEGRO_EVENT ev; - if (redraw && al_is_event_queue_empty(game->_priv.event_queue)) { + if ((redraw && al_is_event_queue_empty(game->_priv.event_queue)) || (game->_priv.gamestate_scheduled)) { + game->_priv.gamestate_scheduled = false; struct Gamestate *tmp = game->_priv.gamestates; - game->_priv.cur_gamestate.toLoad = 0; - game->_priv.cur_gamestate.loaded = 0; + game->_priv.tmp_gamestate.toLoad = 0; + game->_priv.tmp_gamestate.loaded = 0; // FIXME: move to function // TODO: support dependences while (tmp) { if (tmp->pending_stop) { PrintConsole(game, "Stopping gamestate \"%s\"...", tmp->name); + game->_priv.current_gamestate = tmp; (*tmp->api.Gamestate_Stop)(game, tmp->data); tmp->started = false; tmp->pending_stop = false; } - if (tmp->pending_load) game->_priv.cur_gamestate.toLoad++; + if (tmp->pending_load) game->_priv.tmp_gamestate.toLoad++; tmp=tmp->next; } @@ -255,7 +258,7 @@ SYMBOL_EXPORT int libsuperderpy_run(struct Game *game) { // FIXME: move to function // TODO: support dependences - game->_priv.cur_gamestate.t = -1; + game->_priv.tmp_gamestate.t = -1; while (tmp) { if (tmp->pending_unload) { @@ -263,6 +266,7 @@ SYMBOL_EXPORT int libsuperderpy_run(struct Game *game) { al_stop_timer(game->_priv.timer); tmp->loaded = false; tmp->pending_unload = false; + game->_priv.current_gamestate = tmp; (*tmp->api.Gamestate_Unload)(game, tmp->data); dlclose(tmp->handle); tmp->handle = NULL; @@ -300,20 +304,21 @@ SYMBOL_EXPORT int libsuperderpy_run(struct Game *game) { if (!(tmp->api.Gamestate_ProgressCount = dlsym(tmp->handle, "Gamestate_ProgressCount"))) { GS_ERROR; } - game->_priv.cur_gamestate.p = 0; + game->_priv.tmp_gamestate.p = 0; DrawGamestates(game); if (tmp->showLoading) { - (*game->_priv.loading.Draw)(game, game->_priv.loading.data, game->_priv.cur_gamestate.loaded/(float)game->_priv.cur_gamestate.toLoad); + (*game->_priv.loading.Draw)(game, game->_priv.loading.data, game->_priv.tmp_gamestate.loaded/(float)game->_priv.tmp_gamestate.toLoad); } DrawConsole(game); - if (al_get_time() - game->_priv.cur_gamestate.t >= 1/60.0) { + if (al_get_time() - game->_priv.tmp_gamestate.t >= 1/60.0) { al_flip_display(); - game->_priv.cur_gamestate.t = al_get_time(); + game->_priv.tmp_gamestate.t = al_get_time(); } - game->_priv.cur_gamestate.tmp = tmp; + game->_priv.tmp_gamestate.tmp = tmp; + game->_priv.current_gamestate = tmp; tmp->data = (*tmp->api.Gamestate_Load)(game, &GamestateProgress); - game->_priv.cur_gamestate.loaded++; + game->_priv.tmp_gamestate.loaded++; tmp->loaded = true; tmp->pending_load = false; @@ -331,6 +336,7 @@ SYMBOL_EXPORT int libsuperderpy_run(struct Game *game) { if ((tmp->pending_start) && (tmp->loaded)) { PrintConsole(game, "Starting gamestate \"%s\"...", tmp->name); al_stop_timer(game->_priv.timer); + game->_priv.current_gamestate = tmp; (*tmp->api.Gamestate_Start)(game, tmp->data); al_start_timer(game->_priv.timer); tmp->started = true; @@ -421,11 +427,13 @@ SYMBOL_EXPORT void libsuperderpy_destroy(struct Game *game) { while (tmp) { if (tmp->started) { PrintConsole(game, "Stopping gamestate \"%s\"...", tmp->name); + game->_priv.current_gamestate = tmp; (*tmp->api.Gamestate_Stop)(game, tmp->data); tmp->started = false; } if (tmp->loaded) { PrintConsole(game, "Unloading gamestate \"%s\"...", tmp->name); + game->_priv.current_gamestate = tmp; (*tmp->api.Gamestate_Unload)(game, tmp->data); dlclose(tmp->handle); tmp->loaded = false; diff --git a/src/libsuperderpy.h b/src/libsuperderpy.h index e7111ba..2de6e93 100644 --- a/src/libsuperderpy.h +++ b/src/libsuperderpy.h @@ -75,6 +75,7 @@ struct Game { struct { struct Gamestate *gamestates; /*!< List of known gamestates. */ + bool gamestate_scheduled; /*!< Whether there's some gamestate lifecycle management work to do. */ ALLEGRO_FONT *font_console; /*!< Font used in game console. */ ALLEGRO_FONT *font_bsod; /*!< Font used in Blue Screens of Derp. */ ALLEGRO_BITMAP *console; /*!< Bitmap with game console. */ @@ -107,7 +108,9 @@ struct Game { struct Gamestate *tmp; double t; int loaded, toLoad; - } cur_gamestate; + } tmp_gamestate; + + struct Gamestate *current_gamestate; struct libsuperderpy_list *garbage;