mirror of
https://gitlab.com/dosowisko.net/libsuperderpy.git
synced 2025-02-07 21:56:44 +01:00
reorganize Game structure, deprecate access to _priv fields
This commit is contained in:
parent
23b11b1a5b
commit
ce66ba8060
7 changed files with 174 additions and 165 deletions
|
@ -21,33 +21,33 @@
|
||||||
#include "3rdparty/valgrind.h"
|
#include "3rdparty/valgrind.h"
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
|
|
||||||
SYMBOL_INTERNAL void SimpleCompositor(struct Game* game, struct Gamestate* gamestates) {
|
SYMBOL_INTERNAL void SimpleCompositor(struct Game* game, struct Gamestate* gamestates, ALLEGRO_BITMAP* loading_fb) {
|
||||||
struct Gamestate* tmp = gamestates;
|
struct Gamestate* tmp = gamestates;
|
||||||
ClearToColor(game, al_map_rgb(0, 0, 0));
|
ClearToColor(game, al_map_rgb(0, 0, 0));
|
||||||
while (tmp) {
|
while (tmp) {
|
||||||
if ((tmp->loaded) && (tmp->started)) {
|
if ((tmp->loaded) && (tmp->started)) {
|
||||||
al_draw_bitmap(tmp->fb, game->_priv.clip_rect.x, game->_priv.clip_rect.y, 0);
|
al_draw_bitmap(tmp->fb, game->clip_rect.x, game->clip_rect.y, 0);
|
||||||
}
|
}
|
||||||
tmp = tmp->next;
|
tmp = tmp->next;
|
||||||
}
|
}
|
||||||
if (game->_priv.loading.shown) {
|
if (game->loading.shown) {
|
||||||
al_draw_bitmap(game->loading_fb, game->_priv.clip_rect.x, game->_priv.clip_rect.y, 0);
|
al_draw_bitmap(loading_fb, game->clip_rect.x, game->clip_rect.y, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SYMBOL_INTERNAL void DrawGamestates(struct Game* game) {
|
SYMBOL_INTERNAL void DrawGamestates(struct Game* game) {
|
||||||
if (!game->handlers.compositor) {
|
if (!game->_priv.params.handlers.compositor) {
|
||||||
ClearScreen(game);
|
ClearScreen(game);
|
||||||
}
|
}
|
||||||
struct Gamestate* tmp = game->_priv.gamestates;
|
struct Gamestate* tmp = game->_priv.gamestates;
|
||||||
if (game->handlers.predraw) {
|
if (game->_priv.params.handlers.predraw) {
|
||||||
game->handlers.predraw(game);
|
game->_priv.params.handlers.predraw(game);
|
||||||
}
|
}
|
||||||
while (tmp) {
|
while (tmp) {
|
||||||
if ((tmp->loaded) && (tmp->started)) {
|
if ((tmp->loaded) && (tmp->started)) {
|
||||||
game->_priv.current_gamestate = tmp;
|
game->_priv.current_gamestate = tmp;
|
||||||
SetFramebufferAsTarget(game);
|
SetFramebufferAsTarget(game);
|
||||||
if (game->handlers.compositor) { // don't clear when uncomposited
|
if (game->_priv.params.handlers.compositor) { // don't clear when uncomposited
|
||||||
al_reset_clipping_rectangle();
|
al_reset_clipping_rectangle();
|
||||||
al_clear_to_color(al_map_rgb(0, 0, 0)); // even if everything is going to be redrawn, it optimizes tiled rendering
|
al_clear_to_color(al_map_rgb(0, 0, 0)); // even if everything is going to be redrawn, it optimizes tiled rendering
|
||||||
}
|
}
|
||||||
|
@ -57,11 +57,11 @@ SYMBOL_INTERNAL void DrawGamestates(struct Game* game) {
|
||||||
tmp = tmp->next;
|
tmp = tmp->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (game->_priv.loading.inProgress) {
|
if (game->_priv.loading.in_progress) {
|
||||||
// same as above, but for the loading gamestate
|
// same as above, but for the loading gamestate
|
||||||
game->_priv.current_gamestate = NULL;
|
game->_priv.current_gamestate = NULL;
|
||||||
SetFramebufferAsTarget(game);
|
SetFramebufferAsTarget(game);
|
||||||
if (game->handlers.compositor) {
|
if (game->_priv.params.handlers.compositor) {
|
||||||
al_reset_clipping_rectangle();
|
al_reset_clipping_rectangle();
|
||||||
al_clear_to_color(al_map_rgb(0, 0, 0));
|
al_clear_to_color(al_map_rgb(0, 0, 0));
|
||||||
}
|
}
|
||||||
|
@ -76,19 +76,19 @@ SYMBOL_INTERNAL void DrawGamestates(struct Game* game) {
|
||||||
al_use_transform(&t);
|
al_use_transform(&t);
|
||||||
al_reset_clipping_rectangle();
|
al_reset_clipping_rectangle();
|
||||||
|
|
||||||
if (game->handlers.compositor) {
|
if (game->_priv.params.handlers.compositor) {
|
||||||
game->handlers.compositor(game, game->_priv.gamestates);
|
game->_priv.params.handlers.compositor(game, game->_priv.gamestates, game->_priv.loading.fb);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (game->handlers.postdraw) {
|
if (game->_priv.params.handlers.postdraw) {
|
||||||
game->handlers.postdraw(game);
|
game->_priv.params.handlers.postdraw(game);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SYMBOL_INTERNAL void LogicGamestates(struct Game* game, double delta) {
|
SYMBOL_INTERNAL void LogicGamestates(struct Game* game, double delta) {
|
||||||
struct Gamestate* tmp = game->_priv.gamestates;
|
struct Gamestate* tmp = game->_priv.gamestates;
|
||||||
if (game->handlers.prelogic) {
|
if (game->_priv.params.handlers.prelogic) {
|
||||||
game->handlers.prelogic(game, delta);
|
game->_priv.params.handlers.prelogic(game, delta);
|
||||||
}
|
}
|
||||||
while (tmp) {
|
while (tmp) {
|
||||||
if ((tmp->loaded) && (tmp->started) && (!tmp->paused)) {
|
if ((tmp->loaded) && (tmp->started) && (!tmp->paused)) {
|
||||||
|
@ -97,8 +97,8 @@ SYMBOL_INTERNAL void LogicGamestates(struct Game* game, double delta) {
|
||||||
}
|
}
|
||||||
tmp = tmp->next;
|
tmp = tmp->next;
|
||||||
}
|
}
|
||||||
if (game->handlers.postlogic) {
|
if (game->_priv.params.handlers.postlogic) {
|
||||||
game->handlers.postlogic(game, delta);
|
game->_priv.params.handlers.postlogic(game, delta);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,18 +166,18 @@ SYMBOL_INTERNAL void ResizeGamestates(struct Game* game) {
|
||||||
struct Gamestate* tmp = game->_priv.gamestates;
|
struct Gamestate* tmp = game->_priv.gamestates;
|
||||||
while (tmp) {
|
while (tmp) {
|
||||||
al_destroy_bitmap(tmp->fb);
|
al_destroy_bitmap(tmp->fb);
|
||||||
if (game->handlers.compositor) {
|
if (game->_priv.params.handlers.compositor) {
|
||||||
tmp->fb = CreateNotPreservedBitmap(game->_priv.clip_rect.w, game->_priv.clip_rect.h);
|
tmp->fb = CreateNotPreservedBitmap(game->clip_rect.w, game->clip_rect.h);
|
||||||
} else {
|
} else {
|
||||||
tmp->fb = al_create_sub_bitmap(al_get_backbuffer(game->display), game->_priv.clip_rect.x, game->_priv.clip_rect.y, game->_priv.clip_rect.w, game->_priv.clip_rect.h);
|
tmp->fb = al_create_sub_bitmap(al_get_backbuffer(game->display), game->clip_rect.x, game->clip_rect.y, game->clip_rect.w, game->clip_rect.h);
|
||||||
}
|
}
|
||||||
tmp = tmp->next;
|
tmp = tmp->next;
|
||||||
}
|
}
|
||||||
al_destroy_bitmap(game->loading_fb);
|
al_destroy_bitmap(game->_priv.loading.fb);
|
||||||
if (game->handlers.compositor) {
|
if (game->_priv.params.handlers.compositor) {
|
||||||
game->loading_fb = CreateNotPreservedBitmap(game->_priv.clip_rect.w, game->_priv.clip_rect.h);
|
game->_priv.loading.fb = CreateNotPreservedBitmap(game->clip_rect.w, game->clip_rect.h);
|
||||||
} else {
|
} else {
|
||||||
game->loading_fb = al_create_sub_bitmap(al_get_backbuffer(game->display), game->_priv.clip_rect.x, game->_priv.clip_rect.y, game->_priv.clip_rect.w, game->_priv.clip_rect.h);
|
game->_priv.loading.fb = al_create_sub_bitmap(al_get_backbuffer(game->display), game->clip_rect.x, game->clip_rect.y, game->clip_rect.w, game->clip_rect.h);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,7 +215,7 @@ SYMBOL_INTERNAL void DrawConsole(struct Game* game) {
|
||||||
DrawTimelines(game);
|
DrawTimelines(game);
|
||||||
|
|
||||||
al_hold_bitmap_drawing(false);
|
al_hold_bitmap_drawing(false);
|
||||||
al_use_transform(&game->projection);
|
al_use_transform(&game->_priv.projection);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (game_time - game->_priv.fps_count.old_time >= 1.0) {
|
if (game_time - game->_priv.fps_count.old_time >= 1.0) {
|
||||||
|
@ -228,11 +228,11 @@ SYMBOL_INTERNAL void DrawConsole(struct Game* game) {
|
||||||
}
|
}
|
||||||
|
|
||||||
SYMBOL_INTERNAL void Console_Load(struct Game* game) {
|
SYMBOL_INTERNAL void Console_Load(struct Game* game) {
|
||||||
game->_priv.font_console = al_load_ttf_font(GetDataFilePath(game, "fonts/DejaVuSansMono.ttf"), (int)(game->_priv.clip_rect.h * 0.025), 0);
|
game->_priv.font_console = al_load_ttf_font(GetDataFilePath(game, "fonts/DejaVuSansMono.ttf"), (int)(game->clip_rect.h * 0.025), 0);
|
||||||
if (game->_priv.clip_rect.h * 0.025 >= 16) {
|
if (game->clip_rect.h * 0.025 >= 16) {
|
||||||
game->_priv.font_bsod = al_load_ttf_font(GetDataFilePath(game, "fonts/PerfectDOSVGA437.ttf"), 16 * ((game->_priv.clip_rect.h > 1080) ? 2 : 1), 0);
|
game->_priv.font_bsod = al_load_ttf_font(GetDataFilePath(game, "fonts/PerfectDOSVGA437.ttf"), 16 * ((game->clip_rect.h > 1080) ? 2 : 1), 0);
|
||||||
} else {
|
} else {
|
||||||
game->_priv.font_bsod = al_load_ttf_font(GetDataFilePath(game, "fonts/DejaVuSansMono.ttf"), (int)(game->_priv.clip_rect.h * 0.025), 0);
|
game->_priv.font_bsod = al_load_ttf_font(GetDataFilePath(game, "fonts/DejaVuSansMono.ttf"), (int)(game->clip_rect.h * 0.025), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -244,7 +244,7 @@ SYMBOL_INTERNAL void Console_Unload(struct Game* game) {
|
||||||
|
|
||||||
SYMBOL_INTERNAL void* GamestateLoadingThread(void* arg) {
|
SYMBOL_INTERNAL void* GamestateLoadingThread(void* arg) {
|
||||||
struct GamestateLoadingThreadData* data = arg;
|
struct GamestateLoadingThreadData* data = arg;
|
||||||
data->game->_priv.loading.inProgress = true;
|
data->game->_priv.loading.in_progress = true;
|
||||||
al_set_new_bitmap_flags(data->bitmap_flags);
|
al_set_new_bitmap_flags(data->bitmap_flags);
|
||||||
data->gamestate->data = data->gamestate->api->Gamestate_Load(data->game, &GamestateProgress);
|
data->gamestate->data = data->gamestate->api->Gamestate_Load(data->game, &GamestateProgress);
|
||||||
if (data->game->_priv.loading.progress != data->gamestate->progressCount) {
|
if (data->game->_priv.loading.progress != data->gamestate->progressCount) {
|
||||||
|
@ -256,7 +256,7 @@ SYMBOL_INTERNAL void* GamestateLoadingThread(void* arg) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
data->bitmap_flags = al_get_new_bitmap_flags();
|
data->bitmap_flags = al_get_new_bitmap_flags();
|
||||||
data->game->_priv.loading.inProgress = false;
|
data->game->_priv.loading.in_progress = false;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,7 +264,7 @@ SYMBOL_INTERNAL void* ScreenshotThread(void* arg) {
|
||||||
struct ScreenshotThreadData* data = arg;
|
struct ScreenshotThreadData* data = arg;
|
||||||
ALLEGRO_PATH* path = al_get_standard_path(ALLEGRO_USER_DOCUMENTS_PATH);
|
ALLEGRO_PATH* path = al_get_standard_path(ALLEGRO_USER_DOCUMENTS_PATH);
|
||||||
char filename[255];
|
char filename[255];
|
||||||
snprintf(filename, 255, "%s_%ju_%ju.png", data->game->name, (uintmax_t)time(NULL), (uintmax_t)clock());
|
snprintf(filename, 255, "%s_%ju_%ju.png", data->game->_priv.name, (uintmax_t)time(NULL), (uintmax_t)clock());
|
||||||
al_set_path_filename(path, filename);
|
al_set_path_filename(path, filename);
|
||||||
al_save_bitmap(al_path_cstr(path, ALLEGRO_NATIVE_PATH_SEP), data->bitmap);
|
al_save_bitmap(al_path_cstr(path, ALLEGRO_NATIVE_PATH_SEP), data->bitmap);
|
||||||
PrintConsole(data->game, "Screenshot stored in %s", al_path_cstr(path, ALLEGRO_NATIVE_PATH_SEP));
|
PrintConsole(data->game, "Screenshot stored in %s", al_path_cstr(path, ALLEGRO_NATIVE_PATH_SEP));
|
||||||
|
@ -280,7 +280,7 @@ SYMBOL_INTERNAL void CalculateProgress(struct Game* game) {
|
||||||
if (game->config.debug) {
|
if (game->config.debug) {
|
||||||
PrintConsole(game, "[%s] Progress: %d%% (%d/%d)", tmp->name, (int)(progress * 100), game->_priv.loading.progress, tmp->progressCount + 1);
|
PrintConsole(game, "[%s] Progress: %d%% (%d/%d)", tmp->name, (int)(progress * 100), game->_priv.loading.progress, tmp->progressCount + 1);
|
||||||
}
|
}
|
||||||
game->loading_progress = progress;
|
game->loading.progress = progress;
|
||||||
}
|
}
|
||||||
|
|
||||||
SYMBOL_INTERNAL void GamestateProgress(struct Game* game) {
|
SYMBOL_INTERNAL void GamestateProgress(struct Game* game) {
|
||||||
|
@ -310,16 +310,16 @@ SYMBOL_INTERNAL void GamestateProgress(struct Game* game) {
|
||||||
SYMBOL_INTERNAL bool OpenGamestate(struct Game* game, struct Gamestate* gamestate) {
|
SYMBOL_INTERNAL bool OpenGamestate(struct Game* game, struct Gamestate* gamestate) {
|
||||||
PrintConsole(game, "Opening gamestate \"%s\"...", gamestate->name);
|
PrintConsole(game, "Opening gamestate \"%s\"...", gamestate->name);
|
||||||
char libname[1024];
|
char libname[1024];
|
||||||
snprintf(libname, 1024, "libsuperderpy-%s-%s" LIBRARY_EXTENSION, game->name, gamestate->name);
|
snprintf(libname, 1024, "libsuperderpy-%s-%s" LIBRARY_EXTENSION, game->_priv.name, gamestate->name);
|
||||||
gamestate->handle = dlopen(AddGarbage(game, GetLibraryPath(game, libname)), RTLD_NOW);
|
gamestate->handle = dlopen(AddGarbage(game, GetLibraryPath(game, libname)), RTLD_NOW);
|
||||||
if (!gamestate->handle) {
|
if (!gamestate->handle) {
|
||||||
FatalError(game, false, "Error while opening gamestate \"%s\": %s", gamestate->name, dlerror()); // TODO: move out
|
FatalError(game, false, "Error while opening gamestate \"%s\": %s", gamestate->name, dlerror()); // TODO: move out
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (game->handlers.compositor) {
|
if (game->_priv.params.handlers.compositor) {
|
||||||
gamestate->fb = CreateNotPreservedBitmap(game->_priv.clip_rect.w, game->_priv.clip_rect.h);
|
gamestate->fb = CreateNotPreservedBitmap(game->clip_rect.w, game->clip_rect.h);
|
||||||
} else {
|
} else {
|
||||||
gamestate->fb = al_create_sub_bitmap(al_get_backbuffer(game->display), game->_priv.clip_rect.x, game->_priv.clip_rect.y, game->_priv.clip_rect.w, game->_priv.clip_rect.h);
|
gamestate->fb = al_create_sub_bitmap(al_get_backbuffer(game->display), game->clip_rect.x, game->clip_rect.y, game->clip_rect.w, game->clip_rect.h);
|
||||||
}
|
}
|
||||||
gamestate->open = true;
|
gamestate->open = true;
|
||||||
return true;
|
return true;
|
||||||
|
@ -499,10 +499,10 @@ SYMBOL_INTERNAL void ClearScreen(struct Game* game) {
|
||||||
al_set_target_backbuffer(game->display);
|
al_set_target_backbuffer(game->display);
|
||||||
al_reset_clipping_rectangle();
|
al_reset_clipping_rectangle();
|
||||||
al_clear_to_color(al_map_rgb(0, 0, 0));
|
al_clear_to_color(al_map_rgb(0, 0, 0));
|
||||||
if (game->viewport_config.depth_buffer) {
|
if (game->_priv.params.depth_buffer) {
|
||||||
al_clear_depth_buffer(1.0);
|
al_clear_depth_buffer(1.0);
|
||||||
}
|
}
|
||||||
al_set_clipping_rectangle(game->_priv.clip_rect.x, game->_priv.clip_rect.y, game->_priv.clip_rect.w, game->_priv.clip_rect.h);
|
al_set_clipping_rectangle(game->clip_rect.x, game->clip_rect.y, game->clip_rect.w, game->clip_rect.h);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DrawQueue(struct Game* game, struct TM_Action* queue, int clipX, int clipY) {
|
static void DrawQueue(struct Game* game, struct TM_Action* queue, int clipX, int clipY) {
|
||||||
|
@ -511,19 +511,19 @@ static void DrawQueue(struct Game* game, struct TM_Action* queue, int clipX, int
|
||||||
struct TM_Action* pom = queue;
|
struct TM_Action* pom = queue;
|
||||||
while (pom != NULL) {
|
while (pom != NULL) {
|
||||||
int width = al_get_text_width(game->_priv.font_console, pom->name);
|
int width = al_get_text_width(game->_priv.font_console, pom->name);
|
||||||
al_draw_filled_rectangle(pos - (10 / 3200.0) * game->_priv.clip_rect.w, clipY, pos + width + (10 / 3200.0) * game->_priv.clip_rect.w, clipY + (60 / 1800.0) * game->_priv.clip_rect.h, pom->started ? al_map_rgba(255, 255, 255, 192) : al_map_rgba(0, 0, 0, 0));
|
al_draw_filled_rectangle(pos - (10 / 3200.0) * game->clip_rect.w, clipY, pos + width + (10 / 3200.0) * game->clip_rect.w, clipY + (60 / 1800.0) * game->clip_rect.h, pom->started ? al_map_rgba(255, 255, 255, 192) : al_map_rgba(0, 0, 0, 0));
|
||||||
al_draw_rectangle(pos - (10 / 3200.0) * game->_priv.clip_rect.w, clipY, pos + width + (10 / 3200.0) * game->_priv.clip_rect.w, clipY + (60 / 1800.0) * game->_priv.clip_rect.h, al_map_rgb(255, 255, 255), 2);
|
al_draw_rectangle(pos - (10 / 3200.0) * game->clip_rect.w, clipY, pos + width + (10 / 3200.0) * game->clip_rect.w, clipY + (60 / 1800.0) * game->clip_rect.h, al_map_rgb(255, 255, 255), 2);
|
||||||
al_draw_text(game->_priv.font_console, pom->started ? al_map_rgb(0, 0, 0) : al_map_rgb(255, 255, 255), pos, clipY, ALLEGRO_ALIGN_LEFT, pom->name);
|
al_draw_text(game->_priv.font_console, pom->started ? al_map_rgb(0, 0, 0) : al_map_rgb(255, 255, 255), pos, clipY, ALLEGRO_ALIGN_LEFT, pom->name);
|
||||||
|
|
||||||
if (pom->delay) {
|
if (pom->delay) {
|
||||||
al_draw_textf(game->_priv.font_console, al_map_rgb(255, 255, 255), pos, clipY - (50 / 1800.0) * game->_priv.clip_rect.h, ALLEGRO_ALIGN_LEFT, "%d", (int)(pom->delay * 1000));
|
al_draw_textf(game->_priv.font_console, al_map_rgb(255, 255, 255), pos, clipY - (50 / 1800.0) * game->clip_rect.h, ALLEGRO_ALIGN_LEFT, "%d", (int)(pom->delay * 1000));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strncmp(pom->name, "TM_RunInBackground", 18) == 0) { // FIXME: this is crappy way to detect queued background actions
|
if (strncmp(pom->name, "TM_RunInBackground", 18) == 0) { // FIXME: this is crappy way to detect queued background actions
|
||||||
al_draw_textf(game->_priv.font_console, al_map_rgb(255, 255, 255), pos, clipY - (50 / 1800.0) * game->_priv.clip_rect.h, ALLEGRO_ALIGN_LEFT, "%s", (char*)pom->arguments->next->next->value);
|
al_draw_textf(game->_priv.font_console, al_map_rgb(255, 255, 255), pos, clipY - (50 / 1800.0) * game->clip_rect.h, ALLEGRO_ALIGN_LEFT, "%s", (char*)pom->arguments->next->next->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
pos += width + (int)((20 / 3200.0) * game->_priv.clip_rect.w);
|
pos += width + (int)((20 / 3200.0) * game->clip_rect.w);
|
||||||
pom = pom->next;
|
pom = pom->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -618,7 +618,7 @@ SYMBOL_INTERNAL void ResumeExecution(struct Game* game) {
|
||||||
SYMBOL_INTERNAL char* GetGameName(struct Game* game, const char* format) {
|
SYMBOL_INTERNAL char* GetGameName(struct Game* game, const char* format) {
|
||||||
char* result = malloc(sizeof(char) * 255);
|
char* result = malloc(sizeof(char) * 255);
|
||||||
SUPPRESS_WARNING("-Wformat-nonliteral")
|
SUPPRESS_WARNING("-Wformat-nonliteral")
|
||||||
snprintf(result, 255, format, game->name);
|
snprintf(result, 255, format, game->_priv.name);
|
||||||
SUPPRESS_END
|
SUPPRESS_END
|
||||||
return AddGarbage(game, result);
|
return AddGarbage(game, result);
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,7 +72,7 @@ struct ScreenshotThreadData {
|
||||||
ALLEGRO_BITMAP* bitmap;
|
ALLEGRO_BITMAP* bitmap;
|
||||||
};
|
};
|
||||||
|
|
||||||
void SimpleCompositor(struct Game* game, struct Gamestate* gamestates);
|
void SimpleCompositor(struct Game* game, struct Gamestate* gamestates, ALLEGRO_BITMAP* loading_fb);
|
||||||
void DrawGamestates(struct Game* game);
|
void DrawGamestates(struct Game* game);
|
||||||
void LogicGamestates(struct Game* game, double delta);
|
void LogicGamestates(struct Game* game, double delta);
|
||||||
void TickGamestates(struct Game* game);
|
void TickGamestates(struct Game* game);
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
|
|
||||||
static char* GetDefaultWindowWidth(struct Game* game) {
|
static char* GetDefaultWindowWidth(struct Game* game) {
|
||||||
char* buf = malloc(sizeof(char) * 255);
|
char* buf = malloc(sizeof(char) * 255);
|
||||||
double aspect = game->viewport_config.aspect ? game->viewport_config.aspect : (game->viewport_config.width / (double)game->viewport_config.height);
|
double aspect = game->_priv.params.aspect ? game->_priv.params.aspect : (game->_priv.params.width / (double)game->_priv.params.height);
|
||||||
if (aspect < 1.0) {
|
if (aspect < 1.0) {
|
||||||
aspect = 1.0;
|
aspect = 1.0;
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@ static char* GetDefaultWindowWidth(struct Game* game) {
|
||||||
|
|
||||||
static char* GetDefaultWindowHeight(struct Game* game) {
|
static char* GetDefaultWindowHeight(struct Game* game) {
|
||||||
char* buf = malloc(sizeof(char) * 255);
|
char* buf = malloc(sizeof(char) * 255);
|
||||||
double aspect = game->viewport_config.aspect ? game->viewport_config.aspect : (game->viewport_config.width / (double)game->viewport_config.height);
|
double aspect = game->_priv.params.aspect ? game->_priv.params.aspect : (game->_priv.params.width / (double)game->_priv.params.height);
|
||||||
if (aspect > 1.0) {
|
if (aspect > 1.0) {
|
||||||
aspect = 1.0;
|
aspect = 1.0;
|
||||||
}
|
}
|
||||||
|
@ -54,11 +54,11 @@ static char* GetDefaultWindowHeight(struct Game* game) {
|
||||||
return AddGarbage(game, buf);
|
return AddGarbage(game, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
SYMBOL_EXPORT struct Game* libsuperderpy_init(int argc, char** argv, const char* name, struct Viewport viewport) {
|
SYMBOL_EXPORT struct Game* libsuperderpy_init(int argc, char** argv, const char* name, struct Params params) {
|
||||||
struct Game* game = calloc(1, sizeof(struct Game));
|
struct Game* game = calloc(1, sizeof(struct Game));
|
||||||
|
|
||||||
game->name = name;
|
game->_priv.name = name;
|
||||||
game->viewport_config = viewport;
|
game->_priv.params = params;
|
||||||
|
|
||||||
#ifdef ALLEGRO_MACOSX
|
#ifdef ALLEGRO_MACOSX
|
||||||
getcwd(game->_priv.cwd, MAXPATHLEN);
|
getcwd(game->_priv.cwd, MAXPATHLEN);
|
||||||
|
@ -93,14 +93,6 @@ SYMBOL_EXPORT struct Game* libsuperderpy_init(int argc, char** argv, const char*
|
||||||
|
|
||||||
game->_priv.paused = false;
|
game->_priv.paused = false;
|
||||||
|
|
||||||
game->handlers.event = NULL;
|
|
||||||
game->handlers.destroy = NULL;
|
|
||||||
game->handlers.compositor = NULL;
|
|
||||||
game->handlers.prelogic = NULL;
|
|
||||||
game->handlers.postlogic = NULL;
|
|
||||||
game->handlers.predraw = NULL;
|
|
||||||
game->handlers.postdraw = NULL;
|
|
||||||
|
|
||||||
game->_priv.texture_sync = false;
|
game->_priv.texture_sync = false;
|
||||||
game->_priv.texture_sync_cond = al_create_cond();
|
game->_priv.texture_sync_cond = al_create_cond();
|
||||||
game->_priv.texture_sync_mutex = al_create_mutex();
|
game->_priv.texture_sync_mutex = al_create_mutex();
|
||||||
|
@ -156,8 +148,8 @@ SYMBOL_EXPORT struct Game* libsuperderpy_init(int argc, char** argv, const char*
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
game->mouse = al_install_mouse();
|
game->input.available.mouse = al_install_mouse();
|
||||||
if (!game->mouse) {
|
if (!game->input.available.mouse) {
|
||||||
fprintf(stderr, "failed to initialize the mouse!\n");
|
fprintf(stderr, "failed to initialize the mouse!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,10 +163,10 @@ SYMBOL_EXPORT struct Game* libsuperderpy_init(int argc, char** argv, const char*
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
game->touch = false;
|
game->input.available.touch = false;
|
||||||
|
|
||||||
if (!strtol(GetConfigOptionDefault(game, "SuperDerpy", "disableTouch", "0"), NULL, 10)) {
|
if (!strtol(GetConfigOptionDefault(game, "SuperDerpy", "disableTouch", "0"), NULL, 10)) {
|
||||||
game->touch = al_install_touch_input();
|
game->input.available.touch = al_install_touch_input();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef LIBSUPERDERPY_MOUSE_EMULATION
|
#ifdef LIBSUPERDERPY_MOUSE_EMULATION
|
||||||
|
@ -183,10 +175,10 @@ SYMBOL_EXPORT struct Game* libsuperderpy_init(int argc, char** argv, const char*
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
game->joystick = false;
|
game->input.available.joystick = false;
|
||||||
|
|
||||||
if (!strtol(GetConfigOptionDefault(game, "SuperDerpy", "disableJoystick", "0"), NULL, 10)) {
|
if (!strtol(GetConfigOptionDefault(game, "SuperDerpy", "disableJoystick", "0"), NULL, 10)) {
|
||||||
game->joystick = al_install_joystick();
|
game->input.available.joystick = al_install_joystick();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ALLEGRO_ANDROID
|
#ifdef ALLEGRO_ANDROID
|
||||||
|
@ -211,7 +203,7 @@ SYMBOL_EXPORT struct Game* libsuperderpy_init(int argc, char** argv, const char*
|
||||||
al_set_new_display_option(ALLEGRO_SUPPORTED_ORIENTATIONS, ALLEGRO_DISPLAY_ORIENTATION_PORTRAIT, ALLEGRO_SUGGEST);
|
al_set_new_display_option(ALLEGRO_SUPPORTED_ORIENTATIONS, ALLEGRO_DISPLAY_ORIENTATION_PORTRAIT, ALLEGRO_SUGGEST);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (viewport.depth_buffer) {
|
if (params.depth_buffer) {
|
||||||
al_set_new_display_option(ALLEGRO_DEPTH_SIZE, 24, ALLEGRO_SUGGEST);
|
al_set_new_display_option(ALLEGRO_DEPTH_SIZE, 24, ALLEGRO_SUGGEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,7 +211,8 @@ SYMBOL_EXPORT struct Game* libsuperderpy_init(int argc, char** argv, const char*
|
||||||
al_set_new_window_position(20, 40); // workaround nasty Windows bug with window being created off-screen
|
al_set_new_window_position(20, 40); // workaround nasty Windows bug with window being created off-screen
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
al_set_new_window_title(al_get_app_name());
|
al_set_new_window_title(game->_priv.params.window_title ? game->_priv.params.window_title : al_get_app_name());
|
||||||
|
|
||||||
game->display = al_create_display(game->config.width, game->config.height);
|
game->display = al_create_display(game->config.width, game->config.height);
|
||||||
if (!game->display) {
|
if (!game->display) {
|
||||||
fprintf(stderr, "Failed to create display!\n");
|
fprintf(stderr, "Failed to create display!\n");
|
||||||
|
@ -269,7 +262,7 @@ SYMBOL_EXPORT struct Game* libsuperderpy_init(int argc, char** argv, const char*
|
||||||
if (game->config.fullscreen) { al_hide_mouse_cursor(game->display); }
|
if (game->config.fullscreen) { al_hide_mouse_cursor(game->display); }
|
||||||
al_inhibit_screensaver(true);
|
al_inhibit_screensaver(true);
|
||||||
|
|
||||||
SetupViewport(game, viewport);
|
SetupViewport(game);
|
||||||
|
|
||||||
al_add_new_bitmap_flag(ALLEGRO_MIN_LINEAR | ALLEGRO_MAG_LINEAR);
|
al_add_new_bitmap_flag(ALLEGRO_MIN_LINEAR | ALLEGRO_MAG_LINEAR);
|
||||||
|
|
||||||
|
@ -317,17 +310,15 @@ SYMBOL_EXPORT struct Game* libsuperderpy_init(int argc, char** argv, const char*
|
||||||
|
|
||||||
game->data = NULL;
|
game->data = NULL;
|
||||||
|
|
||||||
game->shutting_down = false;
|
game->_priv.shutting_down = false;
|
||||||
game->restart = false;
|
game->_priv.restart = false;
|
||||||
|
|
||||||
game->show_loading_on_launch = false;
|
game->loading.progress = 0;
|
||||||
|
|
||||||
game->loading_progress = 0;
|
if (game->_priv.params.handlers.compositor) {
|
||||||
|
game->_priv.loading.fb = CreateNotPreservedBitmap(game->clip_rect.w, game->clip_rect.h);
|
||||||
if (game->handlers.compositor) {
|
|
||||||
game->loading_fb = CreateNotPreservedBitmap(game->_priv.clip_rect.w, game->_priv.clip_rect.h);
|
|
||||||
} else {
|
} else {
|
||||||
game->loading_fb = al_create_sub_bitmap(al_get_backbuffer(game->display), game->_priv.clip_rect.x, game->_priv.clip_rect.y, game->_priv.clip_rect.w, game->_priv.clip_rect.h);
|
game->_priv.loading.fb = al_create_sub_bitmap(al_get_backbuffer(game->display), game->clip_rect.x, game->clip_rect.y, game->clip_rect.w, game->clip_rect.h);
|
||||||
}
|
}
|
||||||
|
|
||||||
return game;
|
return game;
|
||||||
|
@ -336,13 +327,13 @@ SYMBOL_EXPORT struct Game* libsuperderpy_init(int argc, char** argv, const char*
|
||||||
SYMBOL_EXPORT int libsuperderpy_start(struct Game* game) {
|
SYMBOL_EXPORT int libsuperderpy_start(struct Game* game) {
|
||||||
al_register_event_source(game->_priv.event_queue, al_get_display_event_source(game->display));
|
al_register_event_source(game->_priv.event_queue, al_get_display_event_source(game->display));
|
||||||
al_register_event_source(game->_priv.event_queue, al_get_keyboard_event_source());
|
al_register_event_source(game->_priv.event_queue, al_get_keyboard_event_source());
|
||||||
if (game->mouse) {
|
if (game->input.available.mouse) {
|
||||||
al_register_event_source(game->_priv.event_queue, al_get_mouse_event_source());
|
al_register_event_source(game->_priv.event_queue, al_get_mouse_event_source());
|
||||||
}
|
}
|
||||||
if (game->joystick) {
|
if (game->input.available.joystick) {
|
||||||
al_register_event_source(game->_priv.event_queue, al_get_joystick_event_source());
|
al_register_event_source(game->_priv.event_queue, al_get_joystick_event_source());
|
||||||
}
|
}
|
||||||
if (game->touch) {
|
if (game->input.available.touch) {
|
||||||
al_register_event_source(game->_priv.event_queue, al_get_touch_input_event_source());
|
al_register_event_source(game->_priv.event_queue, al_get_touch_input_event_source());
|
||||||
#ifdef LIBSUPERDERPY_MOUSE_EMULATION
|
#ifdef LIBSUPERDERPY_MOUSE_EMULATION
|
||||||
al_register_event_source(game->_priv.event_queue, al_get_touch_input_mouse_emulation_event_source());
|
al_register_event_source(game->_priv.event_queue, al_get_touch_input_mouse_emulation_event_source());
|
||||||
|
@ -366,7 +357,7 @@ SYMBOL_EXPORT int libsuperderpy_start(struct Game* game) {
|
||||||
struct Gamestate* tmp = game->_priv.gamestates;
|
struct Gamestate* tmp = game->_priv.gamestates;
|
||||||
while (tmp) {
|
while (tmp) {
|
||||||
// don't show loading screen on init if requested
|
// don't show loading screen on init if requested
|
||||||
tmp->showLoading = game->show_loading_on_launch;
|
tmp->showLoading = game->_priv.params.show_loading_on_launch;
|
||||||
tmp = tmp->next;
|
tmp = tmp->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -421,7 +412,7 @@ SYMBOL_EXPORT int libsuperderpy_run(struct Game* game) {
|
||||||
}
|
}
|
||||||
|
|
||||||
SYMBOL_EXPORT void libsuperderpy_destroy(struct Game* game) {
|
SYMBOL_EXPORT void libsuperderpy_destroy(struct Game* game) {
|
||||||
game->shutting_down = true;
|
game->_priv.shutting_down = true;
|
||||||
|
|
||||||
#ifdef LIBSUPERDERPY_IMGUI
|
#ifdef LIBSUPERDERPY_IMGUI
|
||||||
ImGui_ImplAllegro5_Shutdown();
|
ImGui_ImplAllegro5_Shutdown();
|
||||||
|
@ -456,8 +447,8 @@ SYMBOL_EXPORT void libsuperderpy_destroy(struct Game* game) {
|
||||||
CloseGamestate(game, game->_priv.loading.gamestate);
|
CloseGamestate(game, game->_priv.loading.gamestate);
|
||||||
free(game->_priv.loading.gamestate);
|
free(game->_priv.loading.gamestate);
|
||||||
|
|
||||||
if (game->handlers.destroy) {
|
if (game->_priv.params.handlers.destroy) {
|
||||||
(*game->handlers.destroy)(game);
|
(*game->_priv.params.handlers.destroy)(game);
|
||||||
}
|
}
|
||||||
DestroyShaders(game);
|
DestroyShaders(game);
|
||||||
|
|
||||||
|
@ -505,7 +496,7 @@ SYMBOL_EXPORT void libsuperderpy_destroy(struct Game* game) {
|
||||||
#ifndef __EMSCRIPTEN__
|
#ifndef __EMSCRIPTEN__
|
||||||
al_uninstall_system();
|
al_uninstall_system();
|
||||||
char** argv = game->_priv.argv;
|
char** argv = game->_priv.argv;
|
||||||
bool restart = game->restart;
|
bool restart = game->_priv.restart;
|
||||||
free(game);
|
free(game);
|
||||||
if (restart) {
|
if (restart) {
|
||||||
#ifdef ALLEGRO_MACOSX
|
#ifdef ALLEGRO_MACOSX
|
||||||
|
|
|
@ -86,6 +86,12 @@ struct GamestateResources;
|
||||||
|
|
||||||
#define LIBSUPERDERPY_BITMAP_HASHMAP_BUCKETS 16
|
#define LIBSUPERDERPY_BITMAP_HASHMAP_BUCKETS 16
|
||||||
|
|
||||||
|
#if !defined(LIBSUPERDERPY_INTERNAL_H) && defined(__GNUC__)
|
||||||
|
#define LIBSUPERDERPY_DEPRECATED_PRIV __attribute__((deprecated))
|
||||||
|
#else
|
||||||
|
#define LIBSUPERDERPY_DEPRECATED_PRIV
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(ALLEGRO_WINDOWS) && !defined(LIBSUPERDERPY_NO_MAIN_MANGLING)
|
#if defined(ALLEGRO_WINDOWS) && !defined(LIBSUPERDERPY_NO_MAIN_MANGLING)
|
||||||
int _libsuperderpy_main(int argc, char** argv);
|
int _libsuperderpy_main(int argc, char** argv);
|
||||||
#define main(a, b) \
|
#define main(a, b) \
|
||||||
|
@ -101,21 +107,47 @@ int _libsuperderpy_main(int argc, char** argv);
|
||||||
int _libsuperderpy_main(a, b)
|
int _libsuperderpy_main(a, b)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct Viewport {
|
/*! \brief A list of user callbacks to register. */
|
||||||
|
struct Handlers {
|
||||||
|
bool (*event)(struct Game* game, ALLEGRO_EVENT* ev);
|
||||||
|
void (*destroy)(struct Game* game);
|
||||||
|
void (*compositor)(struct Game* game, struct Gamestate* gamestates, ALLEGRO_BITMAP* loading_fb);
|
||||||
|
void (*prelogic)(struct Game* game, double delta);
|
||||||
|
void (*postlogic)(struct Game* game, double delta);
|
||||||
|
void (*predraw)(struct Game* game);
|
||||||
|
void (*postdraw)(struct Game* game);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*! \brief Parameters for engine initialization. All values default to 0/false/NULL. */
|
||||||
|
struct Params {
|
||||||
int width; /*!< Width of the drawing canvas. */
|
int width; /*!< Width of the drawing canvas. */
|
||||||
int height; /*!< Height of the drawing canvas. */
|
int height; /*!< Height of the drawing canvas. */
|
||||||
float aspect; /*!< When set instead of width/height pair, makes the viewport side fluid; when non-zero, locks its aspect ratio. */
|
float aspect; /*!< When set instead of width/height pair, makes the viewport side fluid; when non-zero, locks its aspect ratio. */
|
||||||
bool integer_scaling; /*!< Ensure that the viewport is zoomed only with integer factors. */
|
bool integer_scaling; /*!< Ensure that the viewport is zoomed only with integer factors. */
|
||||||
bool depth_buffer; /*!< Request a depth buffer for the framebuffer's render target. */
|
bool depth_buffer; /*!< Request a depth buffer for the framebuffer's render target. */
|
||||||
|
bool show_loading_on_launch; /*!< Whether the loading screen should be shown when loading the initial set of gamestates. */
|
||||||
|
char* window_title; /*!< A title of the game's window. When NULL, al_get_app_name() is used. */
|
||||||
|
struct Handlers handlers; /*!< A list of user callbacks to register. */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*! \brief Main struct of the game. */
|
/*! \brief Main struct of the game. */
|
||||||
struct Game {
|
struct Game {
|
||||||
ALLEGRO_DISPLAY* display; /*!< Main Allegro display. */
|
ALLEGRO_DISPLAY* display; /*!< Main Allegro display. */
|
||||||
|
ALLEGRO_EVENT_SOURCE event_source; /*!< Event source for user events. */
|
||||||
|
struct {
|
||||||
|
ALLEGRO_VOICE* v; /*!< Main voice used by the game. */
|
||||||
|
ALLEGRO_MIXER* mixer; /*!< Main mixer of the game. */
|
||||||
|
ALLEGRO_MIXER* music; /*!< Music mixer. */
|
||||||
|
ALLEGRO_MIXER* voice; /*!< Voice mixer. */
|
||||||
|
ALLEGRO_MIXER* fx; /*!< Effects mixer. */
|
||||||
|
} audio; /*!< Audio resources. */
|
||||||
|
|
||||||
ALLEGRO_TRANSFORM projection; /*!< Projection of the game canvas into the actual game window. */
|
LIBSUPERDERPY_DATA_TYPE* data; /*!< User defined structure. */
|
||||||
|
|
||||||
struct Viewport viewport, viewport_config;
|
struct {
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
} viewport; /*!< Canvas size. */
|
||||||
|
|
||||||
double time; /*!< In-game total passed time in seconds. */
|
double time; /*!< In-game total passed time in seconds. */
|
||||||
|
|
||||||
|
@ -128,17 +160,29 @@ struct Game {
|
||||||
bool debug; /*!< Toggles debug mode. */
|
bool debug; /*!< Toggles debug mode. */
|
||||||
int width; /*!< Width of window as being set in configuration. */
|
int width; /*!< Width of window as being set in configuration. */
|
||||||
int height; /*!< Height of window as being set in configuration. */
|
int height; /*!< Height of window as being set in configuration. */
|
||||||
} config;
|
} config; /*!< Configuration values from the config file. */
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
ALLEGRO_VOICE* v; /*!< Main voice used by the game. */
|
int x, y;
|
||||||
ALLEGRO_MIXER* mixer; /*!< Main mixer of the game. */
|
int w, h;
|
||||||
ALLEGRO_MIXER* music; /*!< Music mixer. */
|
} clip_rect; /*!< Clipping rectangle of the display's backbuffer. */
|
||||||
ALLEGRO_MIXER* voice; /*!< Voice mixer. */
|
|
||||||
ALLEGRO_MIXER* fx; /*!< Effects mixer. */
|
|
||||||
} audio; /*!< Audio resources. */
|
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
float progress;
|
||||||
|
bool shown;
|
||||||
|
} loading; /*!< Data about gamestate loading process. */
|
||||||
|
|
||||||
|
struct {
|
||||||
|
struct {
|
||||||
|
bool touch;
|
||||||
|
bool joystick;
|
||||||
|
bool mouse;
|
||||||
|
} available;
|
||||||
|
} input;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
struct Params params;
|
||||||
|
|
||||||
struct Gamestate* gamestates; /*!< List of known gamestates. */
|
struct Gamestate* gamestates; /*!< List of known gamestates. */
|
||||||
ALLEGRO_FONT* font_console; /*!< Font used in game console. */
|
ALLEGRO_FONT* font_console; /*!< Font used in game console. */
|
||||||
ALLEGRO_FONT* font_bsod; /*!< Font used in Blue Screens of Derp. */
|
ALLEGRO_FONT* font_bsod; /*!< Font used in Blue Screens of Derp. */
|
||||||
|
@ -164,9 +208,9 @@ struct Game {
|
||||||
struct Gamestate* current;
|
struct Gamestate* current;
|
||||||
int progress;
|
int progress;
|
||||||
int loaded, toLoad;
|
int loaded, toLoad;
|
||||||
volatile bool inProgress;
|
volatile bool in_progress;
|
||||||
bool shown;
|
|
||||||
double time;
|
double time;
|
||||||
|
ALLEGRO_BITMAP* fb;
|
||||||
} loading;
|
} loading;
|
||||||
|
|
||||||
struct Gamestate* current_gamestate;
|
struct Gamestate* current_gamestate;
|
||||||
|
@ -175,11 +219,6 @@ struct Game {
|
||||||
|
|
||||||
double timestamp;
|
double timestamp;
|
||||||
|
|
||||||
struct {
|
|
||||||
int x, y;
|
|
||||||
int w, h;
|
|
||||||
} clip_rect;
|
|
||||||
|
|
||||||
bool paused;
|
bool paused;
|
||||||
|
|
||||||
volatile bool texture_sync;
|
volatile bool texture_sync;
|
||||||
|
@ -193,45 +232,25 @@ struct Game {
|
||||||
|
|
||||||
ALLEGRO_MUTEX* mutex;
|
ALLEGRO_MUTEX* mutex;
|
||||||
|
|
||||||
|
const char* name;
|
||||||
|
|
||||||
|
bool shutting_down; /*!< If true then shut down of the game is pending. */
|
||||||
|
bool restart; /*!< If true then restart of the game is pending. */
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
bool verbose, livereload, autopause;
|
bool verbose, livereload, autopause;
|
||||||
} debug;
|
} debug;
|
||||||
|
|
||||||
|
ALLEGRO_TRANSFORM projection; /*!< Projection of the game canvas into the actual game window. */
|
||||||
|
|
||||||
#ifdef ALLEGRO_MACOSX
|
#ifdef ALLEGRO_MACOSX
|
||||||
char cwd[MAXPATHLEN];
|
char cwd[MAXPATHLEN];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
} _priv; /*!< Private resources. Do not use in gamestates! */
|
} _priv LIBSUPERDERPY_DEPRECATED_PRIV; /*!< Private resources. Do not use in gamestates! */
|
||||||
|
|
||||||
bool shutting_down; /*!< If true then shut down of the game is pending. */
|
|
||||||
bool restart; /*!< If true then restart of the game is pending. */
|
|
||||||
bool touch;
|
|
||||||
bool joystick;
|
|
||||||
bool mouse;
|
|
||||||
|
|
||||||
bool show_loading_on_launch;
|
|
||||||
|
|
||||||
const char* name;
|
|
||||||
|
|
||||||
ALLEGRO_EVENT_SOURCE event_source;
|
|
||||||
|
|
||||||
float loading_progress;
|
|
||||||
ALLEGRO_BITMAP* loading_fb;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
bool (*event)(struct Game* game, ALLEGRO_EVENT* ev);
|
|
||||||
void (*destroy)(struct Game* game);
|
|
||||||
void (*compositor)(struct Game* game, struct Gamestate* gamestates);
|
|
||||||
void (*prelogic)(struct Game* game, double delta);
|
|
||||||
void (*postlogic)(struct Game* game, double delta);
|
|
||||||
void (*predraw)(struct Game* game);
|
|
||||||
void (*postdraw)(struct Game* game);
|
|
||||||
} handlers;
|
|
||||||
|
|
||||||
LIBSUPERDERPY_DATA_TYPE* data;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Game* libsuperderpy_init(int argc, char** argv, const char* name, struct Viewport viewport);
|
struct Game* libsuperderpy_init(int argc, char** argv, const char* name, struct Params params);
|
||||||
int libsuperderpy_start(struct Game* game);
|
int libsuperderpy_start(struct Game* game);
|
||||||
int libsuperderpy_run(struct Game* game);
|
int libsuperderpy_run(struct Game* game);
|
||||||
void libsuperderpy_destroy(struct Game* game);
|
void libsuperderpy_destroy(struct Game* game);
|
||||||
|
|
|
@ -49,7 +49,7 @@ static inline void HandleEvent(struct Game* game, ALLEGRO_EVENT* ev) {
|
||||||
#ifdef LIBSUPERDERPY_IMGUI
|
#ifdef LIBSUPERDERPY_IMGUI
|
||||||
ImGui_ImplAllegro5_CreateDeviceObjects();
|
ImGui_ImplAllegro5_CreateDeviceObjects();
|
||||||
#endif
|
#endif
|
||||||
SetupViewport(game, game->viewport_config);
|
SetupViewport(game);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ALLEGRO_EVENT_KEY_DOWN:
|
case ALLEGRO_EVENT_KEY_DOWN:
|
||||||
|
@ -195,7 +195,7 @@ static inline bool MainloopTick(struct Game* game) {
|
||||||
|
|
||||||
game->_priv.loading.toLoad = 0;
|
game->_priv.loading.toLoad = 0;
|
||||||
game->_priv.loading.loaded = 0;
|
game->_priv.loading.loaded = 0;
|
||||||
game->loading_progress = 0;
|
game->loading.progress = 0;
|
||||||
|
|
||||||
// TODO: support gamestate dependences/ordering
|
// TODO: support gamestate dependences/ordering
|
||||||
while (tmp) {
|
while (tmp) {
|
||||||
|
@ -246,17 +246,17 @@ static inline bool MainloopTick(struct Game* game) {
|
||||||
game->_priv.current_gamestate = tmp;
|
game->_priv.current_gamestate = tmp;
|
||||||
|
|
||||||
struct GamestateLoadingThreadData data = {.game = game, .gamestate = tmp, .bitmap_flags = al_get_new_bitmap_flags()};
|
struct GamestateLoadingThreadData data = {.game = game, .gamestate = tmp, .bitmap_flags = al_get_new_bitmap_flags()};
|
||||||
game->_priv.loading.inProgress = true;
|
game->_priv.loading.in_progress = true;
|
||||||
double time = al_get_time();
|
double time = al_get_time();
|
||||||
game->_priv.loading.time = time;
|
game->_priv.loading.time = time;
|
||||||
|
|
||||||
CalculateProgress(game);
|
CalculateProgress(game);
|
||||||
#ifndef LIBSUPERDERPY_SINGLE_THREAD
|
#ifndef LIBSUPERDERPY_SINGLE_THREAD
|
||||||
al_run_detached_thread(GamestateLoadingThread, &data);
|
al_run_detached_thread(GamestateLoadingThread, &data);
|
||||||
while (game->_priv.loading.inProgress) {
|
while (game->_priv.loading.in_progress) {
|
||||||
double delta = al_get_time() - game->_priv.loading.time;
|
double delta = al_get_time() - game->_priv.loading.time;
|
||||||
if (tmp->showLoading) {
|
if (tmp->showLoading) {
|
||||||
game->_priv.loading.shown = true;
|
game->loading.shown = true;
|
||||||
(*game->_priv.loading.gamestate->api->Gamestate_Logic)(game, game->_priv.loading.gamestate->data, delta);
|
(*game->_priv.loading.gamestate->api->Gamestate_Logic)(game, game->_priv.loading.gamestate->data, delta);
|
||||||
DrawGamestates(game);
|
DrawGamestates(game);
|
||||||
}
|
}
|
||||||
|
@ -307,7 +307,7 @@ static inline bool MainloopTick(struct Game* game) {
|
||||||
}
|
}
|
||||||
if (tmp->showLoading) {
|
if (tmp->showLoading) {
|
||||||
(*game->_priv.loading.gamestate->api->Gamestate_Stop)(game, game->_priv.loading.gamestate->data);
|
(*game->_priv.loading.gamestate->api->Gamestate_Stop)(game, game->_priv.loading.gamestate->data);
|
||||||
game->_priv.loading.shown = false;
|
game->loading.shown = false;
|
||||||
}
|
}
|
||||||
tmp->showLoading = true;
|
tmp->showLoading = true;
|
||||||
al_resume_timer(game->_priv.timer);
|
al_resume_timer(game->_priv.timer);
|
||||||
|
@ -411,8 +411,8 @@ static inline bool MainloopEvents(struct Game* game) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (game->handlers.event) {
|
if (game->_priv.params.handlers.event) {
|
||||||
if ((*game->handlers.event)(game, &ev)) {
|
if ((*game->_priv.params.handlers.event)(game, &ev)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
46
src/utils.c
46
src/utils.c
|
@ -217,7 +217,7 @@ SYMBOL_EXPORT void FatalErrorWithContext(struct Game* game, int line, const char
|
||||||
fprintf(stderr, "%s:%d [%s]\n%s\n", file, line, func, text);
|
fprintf(stderr, "%s:%d [%s]\n%s\n", file, line, func, text);
|
||||||
|
|
||||||
#ifndef LIBSUPERDERPY_SINGLE_THREAD
|
#ifndef LIBSUPERDERPY_SINGLE_THREAD
|
||||||
if (game->_priv.loading.inProgress) {
|
if (game->_priv.loading.in_progress) {
|
||||||
al_lock_mutex(game->_priv.bsod_mutex);
|
al_lock_mutex(game->_priv.bsod_mutex);
|
||||||
game->_priv.in_bsod = true;
|
game->_priv.in_bsod = true;
|
||||||
game->_priv.bsod_sync = true;
|
game->_priv.bsod_sync = true;
|
||||||
|
@ -251,7 +251,7 @@ SYMBOL_EXPORT void FatalErrorWithContext(struct Game* game, int line, const char
|
||||||
al_set_target_backbuffer(game->display);
|
al_set_target_backbuffer(game->display);
|
||||||
al_clear_to_color(al_map_rgb(0, 0, 170));
|
al_clear_to_color(al_map_rgb(0, 0, 170));
|
||||||
|
|
||||||
const char* header = game->name;
|
const char* header = game->_priv.name;
|
||||||
const int headw = al_get_text_width(game->_priv.font_bsod, header);
|
const int headw = al_get_text_width(game->_priv.font_bsod, header);
|
||||||
|
|
||||||
al_draw_filled_rectangle(offsetx - headw / 2.0 - 4, offsety, 4 + offsetx + headw / 2.0, offsety + fonth, al_map_rgb(170, 170, 170));
|
al_draw_filled_rectangle(offsetx - headw / 2.0 - 4, offsety, 4 + offsetx + headw / 2.0, offsety + fonth, al_map_rgb(170, 170, 170));
|
||||||
|
@ -318,9 +318,9 @@ SYMBOL_EXPORT void FatalErrorWithContext(struct Game* game, int line, const char
|
||||||
done = true;
|
done = true;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
al_use_transform(&game->projection);
|
al_use_transform(&game->_priv.projection);
|
||||||
#ifndef LIBSUPERDERPY_SINGLE_THREAD
|
#ifndef LIBSUPERDERPY_SINGLE_THREAD
|
||||||
if (game->_priv.loading.inProgress) {
|
if (game->_priv.loading.in_progress) {
|
||||||
PrintConsole(game, "Resuming the main thread...");
|
PrintConsole(game, "Resuming the main thread...");
|
||||||
game->_priv.in_bsod = false;
|
game->_priv.in_bsod = false;
|
||||||
al_signal_cond(game->_priv.bsod_cond);
|
al_signal_cond(game->_priv.bsod_cond);
|
||||||
|
@ -448,29 +448,29 @@ SYMBOL_EXPORT void PrintConsoleWithContext(struct Game* game, int line, const ch
|
||||||
al_unlock_mutex(game->_priv.mutex);
|
al_unlock_mutex(game->_priv.mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
SYMBOL_EXPORT void SetupViewport(struct Game* game, struct Viewport config) {
|
SYMBOL_EXPORT void SetupViewport(struct Game* game) {
|
||||||
game->viewport = config;
|
game->viewport.width = game->_priv.params.width;
|
||||||
|
game->viewport.height = game->_priv.params.height;
|
||||||
|
|
||||||
if ((game->viewport.width == 0) || (game->viewport.height == 0)) {
|
if ((game->viewport.width == 0) || (game->viewport.height == 0)) {
|
||||||
game->viewport.height = al_get_display_height(game->display);
|
game->viewport.height = al_get_display_height(game->display);
|
||||||
game->viewport.width = (int)(game->viewport.aspect * game->viewport.height);
|
game->viewport.width = (int)(game->_priv.params.aspect * game->viewport.height);
|
||||||
if (game->viewport.width > al_get_display_width(game->display)) {
|
if (game->viewport.width > al_get_display_width(game->display)) {
|
||||||
game->viewport.width = al_get_display_width(game->display);
|
game->viewport.width = al_get_display_width(game->display);
|
||||||
game->viewport.height = (int)(game->viewport.width / game->viewport.aspect);
|
game->viewport.height = (int)(game->viewport.width / game->_priv.params.aspect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
game->viewport.aspect = game->viewport.width / (float)game->viewport.height;
|
|
||||||
|
|
||||||
al_set_target_backbuffer(game->display);
|
al_set_target_backbuffer(game->display);
|
||||||
al_identity_transform(&game->projection);
|
al_identity_transform(&game->_priv.projection);
|
||||||
al_use_transform(&game->projection);
|
al_use_transform(&game->_priv.projection);
|
||||||
al_reset_clipping_rectangle();
|
al_reset_clipping_rectangle();
|
||||||
|
|
||||||
float resolution = al_get_display_height(game->display) / (float)game->viewport.height;
|
float resolution = al_get_display_height(game->display) / (float)game->viewport.height;
|
||||||
if (al_get_display_width(game->display) / (float)game->viewport.width < resolution) {
|
if (al_get_display_width(game->display) / (float)game->viewport.width < resolution) {
|
||||||
resolution = al_get_display_width(game->display) / (float)game->viewport.width;
|
resolution = al_get_display_width(game->display) / (float)game->viewport.width;
|
||||||
}
|
}
|
||||||
if (game->viewport.integer_scaling) {
|
if (game->_priv.params.integer_scaling) {
|
||||||
resolution = floorf(resolution);
|
resolution = floorf(resolution);
|
||||||
if (floorf(resolution) == 0) {
|
if (floorf(resolution) == 0) {
|
||||||
resolution = 1;
|
resolution = 1;
|
||||||
|
@ -488,16 +488,16 @@ SYMBOL_EXPORT void SetupViewport(struct Game* game, struct Viewport config) {
|
||||||
if (strtol(GetConfigOptionDefault(game, "SuperDerpy", "letterbox", "1"), NULL, 10)) {
|
if (strtol(GetConfigOptionDefault(game, "SuperDerpy", "letterbox", "1"), NULL, 10)) {
|
||||||
int clipX = (al_get_display_width(game->display) - clipWidth) / 2;
|
int clipX = (al_get_display_width(game->display) - clipWidth) / 2;
|
||||||
int clipY = (al_get_display_height(game->display) - clipHeight) / 2;
|
int clipY = (al_get_display_height(game->display) - clipHeight) / 2;
|
||||||
al_build_transform(&game->projection, clipX, clipY, resolution, resolution, 0.0f);
|
al_build_transform(&game->_priv.projection, clipX, clipY, resolution, resolution, 0.0f);
|
||||||
al_set_clipping_rectangle(clipX, clipY, clipWidth, clipHeight);
|
al_set_clipping_rectangle(clipX, clipY, clipWidth, clipHeight);
|
||||||
game->_priv.clip_rect.x = clipX;
|
game->clip_rect.x = clipX;
|
||||||
game->_priv.clip_rect.y = clipY;
|
game->clip_rect.y = clipY;
|
||||||
game->_priv.clip_rect.w = clipWidth;
|
game->clip_rect.w = clipWidth;
|
||||||
game->_priv.clip_rect.h = clipHeight;
|
game->clip_rect.h = clipHeight;
|
||||||
} else if (strtol(GetConfigOptionDefault(game, "SuperDerpy", "scaling", "1"), NULL, 10)) {
|
} else if (strtol(GetConfigOptionDefault(game, "SuperDerpy", "scaling", "1"), NULL, 10)) {
|
||||||
al_build_transform(&game->projection, 0, 0, al_get_display_width(game->display) / (float)game->viewport.width, al_get_display_height(game->display) / (float)game->viewport.height, 0.0f);
|
al_build_transform(&game->_priv.projection, 0, 0, al_get_display_width(game->display) / (float)game->viewport.width, al_get_display_height(game->display) / (float)game->viewport.height, 0.0f);
|
||||||
}
|
}
|
||||||
al_use_transform(&game->projection);
|
al_use_transform(&game->_priv.projection);
|
||||||
Console_Unload(game);
|
Console_Unload(game);
|
||||||
Console_Load(game);
|
Console_Load(game);
|
||||||
ResizeGamestates(game);
|
ResizeGamestates(game);
|
||||||
|
@ -516,7 +516,7 @@ SYMBOL_EXPORT void WindowCoordsToViewport(struct Game* game, int* x, int* y) {
|
||||||
|
|
||||||
SYMBOL_EXPORT ALLEGRO_BITMAP* GetFramebuffer(struct Game* game) {
|
SYMBOL_EXPORT ALLEGRO_BITMAP* GetFramebuffer(struct Game* game) {
|
||||||
if (!game->_priv.current_gamestate) {
|
if (!game->_priv.current_gamestate) {
|
||||||
return game->loading_fb;
|
return game->_priv.loading.fb;
|
||||||
}
|
}
|
||||||
return game->_priv.current_gamestate->fb;
|
return game->_priv.current_gamestate->fb;
|
||||||
}
|
}
|
||||||
|
@ -544,15 +544,15 @@ SYMBOL_EXPORT ALLEGRO_BITMAP* CreateNotPreservedBitmap(int width, int height) {
|
||||||
return bitmap;
|
return bitmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
SYMBOL_EXPORT void EnableCompositor(struct Game* game, void compositor(struct Game* game, struct Gamestate* gamestates)) {
|
SYMBOL_EXPORT void EnableCompositor(struct Game* game, void compositor(struct Game* game, struct Gamestate* gamestates, ALLEGRO_BITMAP* loading_fb)) {
|
||||||
PrintConsole(game, "Compositor enabled.");
|
PrintConsole(game, "Compositor enabled.");
|
||||||
game->handlers.compositor = compositor ? compositor : SimpleCompositor;
|
game->_priv.params.handlers.compositor = compositor ? compositor : SimpleCompositor;
|
||||||
ResizeGamestates(game);
|
ResizeGamestates(game);
|
||||||
}
|
}
|
||||||
|
|
||||||
SYMBOL_EXPORT void DisableCompositor(struct Game* game) {
|
SYMBOL_EXPORT void DisableCompositor(struct Game* game) {
|
||||||
PrintConsole(game, "Compositor disabled.");
|
PrintConsole(game, "Compositor disabled.");
|
||||||
game->handlers.compositor = NULL;
|
game->_priv.params.handlers.compositor = NULL;
|
||||||
ResizeGamestates(game);
|
ResizeGamestates(game);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,6 @@
|
||||||
#define LIBRARY_EXTENSION ".so"
|
#define LIBRARY_EXTENSION ".so"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct Viewport;
|
|
||||||
struct Gamestate;
|
struct Gamestate;
|
||||||
|
|
||||||
/*! \brief Draws rectangle filled with vertical gradient. */
|
/*! \brief Draws rectangle filled with vertical gradient. */
|
||||||
|
@ -80,7 +79,7 @@ __attribute__((__format__(__printf__, 5, 6))) void PrintConsoleWithContext(struc
|
||||||
__attribute__((__format__(__printf__, 6, 7))) void FatalErrorWithContext(struct Game* game, int line, const char* file, const char* func, bool exit, char* format, ...);
|
__attribute__((__format__(__printf__, 6, 7))) void FatalErrorWithContext(struct Game* game, int line, const char* file, const char* func, bool exit, char* format, ...);
|
||||||
#define FatalError(game, exit, format, ...) FatalErrorWithContext(game, __LINE__, __FILE__, __func__, exit, format, ##__VA_ARGS__)
|
#define FatalError(game, exit, format, ...) FatalErrorWithContext(game, __LINE__, __FILE__, __func__, exit, format, ##__VA_ARGS__)
|
||||||
|
|
||||||
void SetupViewport(struct Game* game, struct Viewport config);
|
void SetupViewport(struct Game* game);
|
||||||
|
|
||||||
void WindowCoordsToViewport(struct Game* game, int* x, int* y);
|
void WindowCoordsToViewport(struct Game* game, int* x, int* y);
|
||||||
|
|
||||||
|
@ -90,7 +89,7 @@ void SetFramebufferAsTarget(struct Game* game);
|
||||||
|
|
||||||
ALLEGRO_BITMAP* CreateNotPreservedBitmap(int width, int height);
|
ALLEGRO_BITMAP* CreateNotPreservedBitmap(int width, int height);
|
||||||
|
|
||||||
void EnableCompositor(struct Game* game, void compositor(struct Game* game, struct Gamestate* gamestates));
|
void EnableCompositor(struct Game* game, void compositor(struct Game* game, struct Gamestate* gamestates, ALLEGRO_BITMAP* loading_fb));
|
||||||
void DisableCompositor(struct Game* game);
|
void DisableCompositor(struct Game* game);
|
||||||
|
|
||||||
char* StrToLower(struct Game* game, char* text);
|
char* StrToLower(struct Game* game, char* text);
|
||||||
|
|
Loading…
Reference in a new issue