mirror of
https://gitlab.com/dosowisko.net/libsuperderpy.git
synced 2025-03-04 01:01:28 +01:00
split libsuperderpy function to _init, _run and _destroy
This commit is contained in:
parent
f02caf73a2
commit
ffd44df08b
5 changed files with 207 additions and 200 deletions
|
@ -6,10 +6,6 @@ SET(SRC_LIST
|
|||
libsuperderpy.c
|
||||
)
|
||||
|
||||
add_definitions(-DLIBSUPERDERPY_GAMENAME_PRETTY="${LIBSUPERDERPY_GAMENAME_PRETTY}")
|
||||
add_definitions(-DLIBSUPERDERPY_GAMENAME="${LIBSUPERDERPY_GAMENAME}")
|
||||
add_definitions(-DLIBSUPERDERPY_INITIAL_GAMESTATE="${LIBSUPERDERPY_INITIAL_GAMESTATE}")
|
||||
|
||||
add_library("libsuperderpy" SHARED ${SRC_LIST})
|
||||
|
||||
SET_TARGET_PROPERTIES("libsuperderpy" PROPERTIES PREFIX "")
|
||||
|
|
|
@ -24,9 +24,7 @@
|
|||
*/
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <getopt.h>
|
||||
#include <locale.h>
|
||||
#include <signal.h>
|
||||
#include <dlfcn.h>
|
||||
#include <unistd.h>
|
||||
#include <allegro5/allegro_primitives.h>
|
||||
|
@ -93,20 +91,11 @@ void ResumeGamestates(struct Game *game) {
|
|||
}
|
||||
}
|
||||
|
||||
struct Game* libsuperderpy_init(int argc, char** argv, const char* name) {
|
||||
|
||||
void derp(int sig) {
|
||||
ssize_t __attribute__((unused)) n = write(STDERR_FILENO, "Segmentation fault\nI just don't know what went wrong!\n", 54);
|
||||
abort();
|
||||
}
|
||||
struct Game *game = malloc(sizeof(struct Game));
|
||||
|
||||
// TODO: let's break it up and move the binary out of libsuperderpy!
|
||||
int libsuperderpy(int argc, char **argv){
|
||||
signal(SIGSEGV, derp);
|
||||
|
||||
srand(time(NULL));
|
||||
|
||||
al_set_org_name("dosowisko.net");
|
||||
al_set_app_name(LIBSUPERDERPY_GAMENAME);
|
||||
game->name = name;
|
||||
|
||||
#ifdef ALLEGRO_MACOSX
|
||||
char exe_path[MAXPATHLEN];
|
||||
|
@ -118,198 +107,194 @@ int libsuperderpy(int argc, char **argv){
|
|||
chdir(link_path);
|
||||
#endif
|
||||
|
||||
|
||||
if(!al_init()) {
|
||||
fprintf(stderr, "failed to initialize allegro!\n");
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct Game game;
|
||||
InitConfig(game);
|
||||
|
||||
InitConfig(&game);
|
||||
game->_priv.fps_count.frames_done = 0;
|
||||
game->_priv.fps_count.fps = 0;
|
||||
game->_priv.fps_count.old_time = 0;
|
||||
|
||||
game._priv.fps_count.frames_done = 0;
|
||||
game._priv.fps_count.fps = 0;
|
||||
game._priv.fps_count.old_time = 0;
|
||||
game->_priv.font_bsod = NULL;
|
||||
game->_priv.console = NULL;
|
||||
|
||||
game._priv.font_bsod = NULL;
|
||||
game._priv.console = NULL;
|
||||
|
||||
game.config.fullscreen = atoi(GetConfigOptionDefault(&game, "SuperDerpy", "fullscreen", "1"));
|
||||
game.config.music = atoi(GetConfigOptionDefault(&game, "SuperDerpy", "music", "10"));
|
||||
game.config.voice = atoi(GetConfigOptionDefault(&game, "SuperDerpy", "voice", "10"));
|
||||
game.config.fx = atoi(GetConfigOptionDefault(&game, "SuperDerpy", "fx", "10"));
|
||||
game.config.debug = atoi(GetConfigOptionDefault(&game, "SuperDerpy", "debug", "0"));
|
||||
game.config.width = atoi(GetConfigOptionDefault(&game, "SuperDerpy", "width", "1280"));
|
||||
if (game.config.width<320) game.config.width=320;
|
||||
game.config.height = atoi(GetConfigOptionDefault(&game, "SuperDerpy", "height", "720"));
|
||||
if (game.config.height<180) game.config.height=180;
|
||||
game->config.fullscreen = atoi(GetConfigOptionDefault(game, "SuperDerpy", "fullscreen", "1"));
|
||||
game->config.music = atoi(GetConfigOptionDefault(game, "SuperDerpy", "music", "10"));
|
||||
game->config.voice = atoi(GetConfigOptionDefault(game, "SuperDerpy", "voice", "10"));
|
||||
game->config.fx = atoi(GetConfigOptionDefault(game, "SuperDerpy", "fx", "10"));
|
||||
game->config.debug = atoi(GetConfigOptionDefault(game, "SuperDerpy", "debug", "0"));
|
||||
game->config.width = atoi(GetConfigOptionDefault(game, "SuperDerpy", "width", "1280"));
|
||||
if (game->config.width<320) game->config.width=320;
|
||||
game->config.height = atoi(GetConfigOptionDefault(game, "SuperDerpy", "height", "720"));
|
||||
if (game->config.height<180) game->config.height=180;
|
||||
|
||||
if(!al_init_image_addon()) {
|
||||
fprintf(stderr, "failed to initialize image addon!\n");
|
||||
/*al_show_native_message_box(display, "Error", "Error", "Failed to initialize al_init_image_addon!",
|
||||
NULL, ALLEGRO_MESSAGEBOX_ERROR);*/
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!al_init_acodec_addon()){
|
||||
fprintf(stderr, "failed to initialize audio codecs!\n");
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!al_install_audio()){
|
||||
fprintf(stderr, "failed to initialize audio!\n");
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!al_install_keyboard()){
|
||||
fprintf(stderr, "failed to initialize keyboard!\n");
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!al_init_primitives_addon()){
|
||||
fprintf(stderr, "failed to initialize primitives!\n");
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!al_install_mouse()) {
|
||||
fprintf(stderr, "failed to initialize the mouse!\n");
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
al_init_font_addon();
|
||||
|
||||
if(!al_init_ttf_addon()){
|
||||
fprintf(stderr, "failed to initialize fonts!\n");
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (game.config.fullscreen) al_set_new_display_flags(ALLEGRO_FULLSCREEN_WINDOW);
|
||||
if (game->config.fullscreen) al_set_new_display_flags(ALLEGRO_FULLSCREEN_WINDOW);
|
||||
else al_set_new_display_flags(ALLEGRO_WINDOWED);
|
||||
al_set_new_display_option(ALLEGRO_VSYNC, 2-atoi(GetConfigOptionDefault(&game, "SuperDerpy", "vsync", "1")), ALLEGRO_SUGGEST);
|
||||
al_set_new_display_option(ALLEGRO_OPENGL, atoi(GetConfigOptionDefault(&game, "SuperDerpy", "opengl", "1")), ALLEGRO_SUGGEST);
|
||||
al_set_new_display_option(ALLEGRO_VSYNC, 2-atoi(GetConfigOptionDefault(game, "SuperDerpy", "vsync", "1")), ALLEGRO_SUGGEST);
|
||||
al_set_new_display_option(ALLEGRO_OPENGL, atoi(GetConfigOptionDefault(game, "SuperDerpy", "opengl", "1")), ALLEGRO_SUGGEST);
|
||||
#ifdef ALLEGRO_WINDOWS
|
||||
al_set_new_window_position(20, 40); // workaround nasty Windows bug with window being created off-screen
|
||||
#endif
|
||||
|
||||
game.display = al_create_display(game.config.width, game.config.height);
|
||||
if(!game.display) {
|
||||
game->display = al_create_display(game->config.width, game->config.height);
|
||||
if(!game->display) {
|
||||
fprintf(stderr, "failed to create display!\n");
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SetupViewport(&game);
|
||||
SetupViewport(game);
|
||||
|
||||
PrintConsole(&game, "Viewport %dx%d", game.viewport.width, game.viewport.height);
|
||||
PrintConsole(game, "Viewport %dx%d", game->viewport.width, game->viewport.height);
|
||||
|
||||
ALLEGRO_BITMAP *icon = al_load_bitmap(GetDataFilePath(&game, "icons/" LIBSUPERDERPY_GAMENAME ".png"));
|
||||
al_set_window_title(game.display, LIBSUPERDERPY_GAMENAME_PRETTY);
|
||||
al_set_display_icon(game.display, icon);
|
||||
ALLEGRO_BITMAP *icon = al_load_bitmap(GetDataFilePath(game, GetGameName(game, "icons/%s.png")));
|
||||
al_set_window_title(game->display, game->name);
|
||||
al_set_display_icon(game->display, icon);
|
||||
al_destroy_bitmap(icon);
|
||||
|
||||
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_set_new_bitmap_flags(ALLEGRO_MIN_LINEAR);
|
||||
|
||||
game._priv.gamestates = NULL;
|
||||
game->_priv.gamestates = NULL;
|
||||
|
||||
game._priv.event_queue = al_create_event_queue();
|
||||
if(!game._priv.event_queue) {
|
||||
FatalError(&game, true, "Failed to create event queue.");
|
||||
al_destroy_display(game.display);
|
||||
return -1;
|
||||
game->_priv.event_queue = al_create_event_queue();
|
||||
if(!game->_priv.event_queue) {
|
||||
FatalError(game, true, "Failed to create event queue.");
|
||||
al_destroy_display(game->display);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
game.audio.v = al_create_voice(44100, ALLEGRO_AUDIO_DEPTH_INT16, ALLEGRO_CHANNEL_CONF_2);
|
||||
game.audio.mixer = al_create_mixer(44100, ALLEGRO_AUDIO_DEPTH_FLOAT32, ALLEGRO_CHANNEL_CONF_2);
|
||||
game.audio.fx = al_create_mixer(44100, ALLEGRO_AUDIO_DEPTH_FLOAT32, ALLEGRO_CHANNEL_CONF_2);
|
||||
game.audio.music = al_create_mixer(44100, ALLEGRO_AUDIO_DEPTH_FLOAT32, ALLEGRO_CHANNEL_CONF_2);
|
||||
game.audio.voice = al_create_mixer(44100, ALLEGRO_AUDIO_DEPTH_FLOAT32, ALLEGRO_CHANNEL_CONF_2);
|
||||
al_attach_mixer_to_voice(game.audio.mixer, game.audio.v);
|
||||
al_attach_mixer_to_mixer(game.audio.fx, game.audio.mixer);
|
||||
al_attach_mixer_to_mixer(game.audio.music, game.audio.mixer);
|
||||
al_attach_mixer_to_mixer(game.audio.voice, game.audio.mixer);
|
||||
al_set_mixer_gain(game.audio.fx, game.config.fx/10.0);
|
||||
al_set_mixer_gain(game.audio.music, game.config.music/10.0);
|
||||
al_set_mixer_gain(game.audio.voice, game.config.voice/10.0);
|
||||
game->audio.v = al_create_voice(44100, ALLEGRO_AUDIO_DEPTH_INT16, ALLEGRO_CHANNEL_CONF_2);
|
||||
game->audio.mixer = al_create_mixer(44100, ALLEGRO_AUDIO_DEPTH_FLOAT32, ALLEGRO_CHANNEL_CONF_2);
|
||||
game->audio.fx = al_create_mixer(44100, ALLEGRO_AUDIO_DEPTH_FLOAT32, ALLEGRO_CHANNEL_CONF_2);
|
||||
game->audio.music = al_create_mixer(44100, ALLEGRO_AUDIO_DEPTH_FLOAT32, ALLEGRO_CHANNEL_CONF_2);
|
||||
game->audio.voice = al_create_mixer(44100, ALLEGRO_AUDIO_DEPTH_FLOAT32, ALLEGRO_CHANNEL_CONF_2);
|
||||
al_attach_mixer_to_voice(game->audio.mixer, game->audio.v);
|
||||
al_attach_mixer_to_mixer(game->audio.fx, game->audio.mixer);
|
||||
al_attach_mixer_to_mixer(game->audio.music, game->audio.mixer);
|
||||
al_attach_mixer_to_mixer(game->audio.voice, game->audio.mixer);
|
||||
al_set_mixer_gain(game->audio.fx, game->config.fx/10.0);
|
||||
al_set_mixer_gain(game->audio.music, game->config.music/10.0);
|
||||
al_set_mixer_gain(game->audio.voice, game->config.voice/10.0);
|
||||
|
||||
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_mouse_event_source());
|
||||
al_register_event_source(game._priv.event_queue, al_get_keyboard_event_source());
|
||||
|
||||
game._priv.showconsole = game.config.debug;
|
||||
|
||||
al_clear_to_color(al_map_rgb(0,0,0));
|
||||
game._priv.timer = al_create_timer(ALLEGRO_BPS_TO_SECS(60)); // logic timer
|
||||
if(!game._priv.timer) {
|
||||
FatalError(&game, true, "Failed to create logic timer.");
|
||||
return -1;
|
||||
}
|
||||
al_register_event_source(game._priv.event_queue, al_get_timer_event_source(game._priv.timer));
|
||||
|
||||
al_flip_display();
|
||||
al_start_timer(game._priv.timer);
|
||||
game->_priv.showconsole = game->config.debug;
|
||||
|
||||
setlocale(LC_NUMERIC, "C");
|
||||
|
||||
game.shuttingdown = false;
|
||||
game.restart = false;
|
||||
game->argc = argc;
|
||||
game->argv = argv;
|
||||
|
||||
char* gamestate = strdup(LIBSUPERDERPY_INITIAL_GAMESTATE); // FIXME: don't hardcore gamestate
|
||||
game->data = NULL;
|
||||
|
||||
int c;
|
||||
while ((c = getopt (argc, argv, "l:s:")) != -1)
|
||||
switch (c) {
|
||||
case 'l':
|
||||
free(gamestate);
|
||||
gamestate = strdup("levelX");
|
||||
gamestate[5] = optarg[0];
|
||||
break;
|
||||
case 's':
|
||||
free(gamestate);
|
||||
gamestate = strdup(optarg);
|
||||
break;
|
||||
}
|
||||
game->shuttingdown = false;
|
||||
game->restart = false;
|
||||
|
||||
LoadGamestate(&game, gamestate);
|
||||
game._priv.gamestates->showLoading = false; // we have only one gamestate right now
|
||||
StartGamestate(&game, gamestate);
|
||||
free(gamestate);
|
||||
return game;
|
||||
}
|
||||
|
||||
char libname[1024] = {};
|
||||
snprintf(libname, 1024, "libsuperderpy-%s-loading" LIBRARY_EXTENSION, LIBSUPERDERPY_GAMENAME);
|
||||
void *handle = dlopen(libname, RTLD_NOW);
|
||||
if (!handle) {
|
||||
FatalError(&game, true, "Error while initializing loading screen %s", dlerror());
|
||||
exit(1);
|
||||
} else {
|
||||
int libsuperderpy_run(struct Game *game) {
|
||||
|
||||
#define GS_LOADINGERROR FatalError(&game, true, "Error on resolving loading symbol: %s", dlerror()); exit(1);
|
||||
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_mouse_event_source());
|
||||
al_register_event_source(game->_priv.event_queue, al_get_keyboard_event_source());
|
||||
|
||||
if (!(game._priv.loading.Draw = dlsym(handle, "Draw"))) { GS_LOADINGERROR; }
|
||||
if (!(game._priv.loading.Load = dlsym(handle, "Load"))) { GS_LOADINGERROR; }
|
||||
if (!(game._priv.loading.Start = dlsym(handle, "Start"))) { GS_LOADINGERROR; }
|
||||
if (!(game._priv.loading.Stop = dlsym(handle, "Stop"))) { GS_LOADINGERROR; }
|
||||
if (!(game._priv.loading.Unload = dlsym(handle, "Unload"))) { GS_LOADINGERROR; }
|
||||
al_clear_to_color(al_map_rgb(0,0,0));
|
||||
game->_priv.timer = al_create_timer(ALLEGRO_BPS_TO_SECS(60)); // logic timer
|
||||
if(!game->_priv.timer) {
|
||||
FatalError(game, true, "Failed to create logic timer.");
|
||||
return 1;
|
||||
}
|
||||
al_register_event_source(game->_priv.event_queue, al_get_timer_event_source(game->_priv.timer));
|
||||
|
||||
al_flip_display();
|
||||
al_start_timer(game->_priv.timer);
|
||||
|
||||
struct Gamestate *tmp = game->_priv.gamestates;
|
||||
while (tmp) {
|
||||
// don't show loading screen on init
|
||||
// TODO: make it configurable
|
||||
tmp->showLoading = false;
|
||||
tmp = tmp->next;
|
||||
}
|
||||
|
||||
game._priv.loading.data = (*game._priv.loading.Load)(&game);
|
||||
char libname[1024] = {};
|
||||
snprintf(libname, 1024, "libsuperderpy-%s-loading" LIBRARY_EXTENSION, game->name);
|
||||
void *handle = dlopen(libname, RTLD_NOW);
|
||||
if (!handle) {
|
||||
FatalError(game, true, "Error while initializing loading screen %s", dlerror());
|
||||
return 2;
|
||||
} else {
|
||||
|
||||
#define GS_LOADINGERROR FatalError(game, true, "Error on resolving loading symbol: %s", dlerror()); return 3;
|
||||
|
||||
if (!(game->_priv.loading.Draw = dlsym(handle, "Draw"))) { GS_LOADINGERROR; }
|
||||
if (!(game->_priv.loading.Load = dlsym(handle, "Load"))) { GS_LOADINGERROR; }
|
||||
if (!(game->_priv.loading.Start = dlsym(handle, "Start"))) { GS_LOADINGERROR; }
|
||||
if (!(game->_priv.loading.Stop = dlsym(handle, "Stop"))) { GS_LOADINGERROR; }
|
||||
if (!(game->_priv.loading.Unload = dlsym(handle, "Unload"))) { GS_LOADINGERROR; }
|
||||
}
|
||||
|
||||
game->_priv.loading.data = (*game->_priv.loading.Load)(game);
|
||||
|
||||
bool redraw = false;
|
||||
|
||||
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)) {
|
||||
|
||||
struct Gamestate *tmp = game._priv.gamestates;
|
||||
struct Gamestate *tmp = game->_priv.gamestates;
|
||||
int toLoad = 0, loaded = 0;
|
||||
|
||||
// FIXME: move to function
|
||||
// TODO: support dependences
|
||||
while (tmp) {
|
||||
if ((tmp->pending_start) && (tmp->started)) {
|
||||
PrintConsole(&game, "Stopping gamestate \"%s\"...", tmp->name);
|
||||
(*tmp->api.Gamestate_Stop)(&game, tmp->data);
|
||||
PrintConsole(game, "Stopping gamestate \"%s\"...", tmp->name);
|
||||
(*tmp->api.Gamestate_Stop)(game, tmp->data);
|
||||
tmp->started = false;
|
||||
tmp->pending_start = false;
|
||||
}
|
||||
|
@ -318,7 +303,7 @@ int libsuperderpy(int argc, char **argv){
|
|||
tmp=tmp->next;
|
||||
}
|
||||
|
||||
tmp = game._priv.gamestates;
|
||||
tmp = game->_priv.gamestates;
|
||||
// FIXME: move to function
|
||||
// TODO: support dependences
|
||||
|
||||
|
@ -326,30 +311,30 @@ int libsuperderpy(int argc, char **argv){
|
|||
|
||||
while (tmp) {
|
||||
if ((tmp->pending_load) && (tmp->loaded)) {
|
||||
PrintConsole(&game, "Unloading gamestate \"%s\"...", tmp->name);
|
||||
al_stop_timer(game._priv.timer);
|
||||
PrintConsole(game, "Unloading gamestate \"%s\"...", tmp->name);
|
||||
al_stop_timer(game->_priv.timer);
|
||||
tmp->loaded = false;
|
||||
tmp->pending_load = false;
|
||||
(*tmp->api.Gamestate_Unload)(&game, tmp->data);
|
||||
(*tmp->api.Gamestate_Unload)(game, tmp->data);
|
||||
dlclose(tmp->handle);
|
||||
tmp->handle = NULL;
|
||||
al_start_timer(game._priv.timer);
|
||||
al_start_timer(game->_priv.timer);
|
||||
} else if ((tmp->pending_load) && (!tmp->loaded)) {
|
||||
PrintConsole(&game, "Loading gamestate \"%s\"...", tmp->name);
|
||||
al_stop_timer(game._priv.timer);
|
||||
PrintConsole(game, "Loading gamestate \"%s\"...", tmp->name);
|
||||
al_stop_timer(game->_priv.timer);
|
||||
// TODO: take proper game name
|
||||
char libname[1024];
|
||||
snprintf(libname, 1024, "libsuperderpy-%s-%s" LIBRARY_EXTENSION, LIBSUPERDERPY_GAMENAME, tmp->name);
|
||||
snprintf(libname, 1024, "libsuperderpy-%s-%s" LIBRARY_EXTENSION, game->name, tmp->name);
|
||||
tmp->handle = dlopen(libname,RTLD_NOW);
|
||||
if (!tmp->handle) {
|
||||
//PrintConsole(&game, "Error while loading gamestate \"%s\": %s", tmp->name, dlerror());
|
||||
FatalError(&game, false, "Error while loading gamestate \"%s\": %s", tmp->name, dlerror());
|
||||
FatalError(game, false, "Error while loading gamestate \"%s\": %s", tmp->name, dlerror());
|
||||
|
||||
tmp->pending_load = false;
|
||||
tmp->pending_start = false;
|
||||
} else {
|
||||
|
||||
#define GS_ERROR FatalError(&game, false, "Error on resolving gamestate symbol: %s", dlerror()); tmp->pending_load = false; tmp->pending_start = false; tmp=tmp->next; continue;
|
||||
#define GS_ERROR FatalError(game, false, "Error on resolving gamestate symbol: %s", dlerror()); tmp->pending_load = false; tmp->pending_start = false; tmp=tmp->next; continue;
|
||||
|
||||
if (!(tmp->api.Gamestate_Draw = dlsym(tmp->handle, "Gamestate_Draw"))) { GS_ERROR; }
|
||||
if (!(tmp->api.Gamestate_Logic = dlsym(tmp->handle, "Gamestate_Logic"))) { GS_ERROR; }
|
||||
|
@ -384,37 +369,37 @@ int libsuperderpy(int argc, char **argv){
|
|||
t = al_get_time();
|
||||
|
||||
// initially draw loading screen with empty bar
|
||||
DrawGamestates(&game);
|
||||
DrawGamestates(game);
|
||||
if (tmp->showLoading) {
|
||||
(*game._priv.loading.Draw)(&game, game._priv.loading.data, loaded/(float)toLoad);
|
||||
(*game->_priv.loading.Draw)(game, game->_priv.loading.data, loaded/(float)toLoad);
|
||||
}
|
||||
DrawConsole(&game);
|
||||
DrawConsole(game);
|
||||
if (al_get_time() - t >= 1/60.0) {
|
||||
al_flip_display();
|
||||
}
|
||||
t = al_get_time();
|
||||
tmp->data = (*tmp->api.Gamestate_Load)(&game, &progress); // feel free to replace "progress" with empty function if you want to compile with clang
|
||||
tmp->data = (*tmp->api.Gamestate_Load)(game, &progress); // feel free to replace "progress" with empty function if you want to compile with clang
|
||||
loaded++;
|
||||
|
||||
tmp->loaded = true;
|
||||
tmp->pending_load = false;
|
||||
}
|
||||
al_start_timer(game._priv.timer);
|
||||
al_start_timer(game->_priv.timer);
|
||||
}
|
||||
|
||||
tmp=tmp->next;
|
||||
}
|
||||
|
||||
bool gameActive = false;
|
||||
tmp=game._priv.gamestates;
|
||||
tmp=game->_priv.gamestates;
|
||||
|
||||
while (tmp) {
|
||||
|
||||
if ((tmp->pending_start) && (!tmp->started) && (tmp->loaded)) {
|
||||
PrintConsole(&game, "Starting gamestate \"%s\"...", tmp->name);
|
||||
al_stop_timer(game._priv.timer);
|
||||
(*tmp->api.Gamestate_Start)(&game, tmp->data);
|
||||
al_start_timer(game._priv.timer);
|
||||
PrintConsole(game, "Starting gamestate \"%s\"...", tmp->name);
|
||||
al_stop_timer(game->_priv.timer);
|
||||
(*tmp->api.Gamestate_Start)(game, tmp->data);
|
||||
al_start_timer(game->_priv.timer);
|
||||
tmp->started = true;
|
||||
tmp->pending_start = false;
|
||||
}
|
||||
|
@ -424,83 +409,88 @@ int libsuperderpy(int argc, char **argv){
|
|||
}
|
||||
|
||||
if (!gameActive) {
|
||||
PrintConsole(&game, "No gamestates left, exiting...");
|
||||
PrintConsole(game, "No gamestates left, exiting...");
|
||||
break;
|
||||
}
|
||||
|
||||
DrawGamestates(&game);
|
||||
DrawConsole(&game);
|
||||
DrawGamestates(game);
|
||||
DrawConsole(game);
|
||||
al_flip_display();
|
||||
redraw = false;
|
||||
|
||||
} else {
|
||||
|
||||
al_wait_for_event(game._priv.event_queue, &ev);
|
||||
al_wait_for_event(game->_priv.event_queue, &ev);
|
||||
|
||||
if ((ev.type == ALLEGRO_EVENT_TIMER) && (ev.timer.source == game._priv.timer)) {
|
||||
LogicGamestates(&game);
|
||||
if ((ev.type == ALLEGRO_EVENT_TIMER) && (ev.timer.source == game->_priv.timer)) {
|
||||
LogicGamestates(game);
|
||||
redraw = true;
|
||||
}
|
||||
else if(ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) {
|
||||
break;
|
||||
}
|
||||
else if(ev.type == ALLEGRO_EVENT_DISPLAY_FOUND) {
|
||||
SetupViewport(&game);
|
||||
SetupViewport(game);
|
||||
}
|
||||
#ifdef ALLEGRO_MACOSX
|
||||
else if ((ev.type == ALLEGRO_EVENT_KEY_DOWN) && (ev.keyboard.keycode == 104)) { //TODO: report to upstream
|
||||
#else
|
||||
else if ((ev.type == ALLEGRO_EVENT_KEY_DOWN) && (ev.keyboard.keycode == ALLEGRO_KEY_TILDE)) {
|
||||
#endif
|
||||
game._priv.showconsole = !game._priv.showconsole;
|
||||
game->_priv.showconsole = !game->_priv.showconsole;
|
||||
}
|
||||
else if ((ev.type == ALLEGRO_EVENT_KEY_DOWN) && (game.config.debug) && (ev.keyboard.keycode == ALLEGRO_KEY_F1)) {
|
||||
else if ((ev.type == ALLEGRO_EVENT_KEY_DOWN) && (game->config.debug) && (ev.keyboard.keycode == ALLEGRO_KEY_F1)) {
|
||||
int i;
|
||||
for (i=0; i<512; i++) {
|
||||
LogicGamestates(&game);
|
||||
LogicGamestates(game);
|
||||
}
|
||||
game._priv.showconsole = true;
|
||||
PrintConsole(&game, "DEBUG: 512 frames skipped...");
|
||||
} else if ((ev.type == ALLEGRO_EVENT_KEY_DOWN) && (game.config.debug) && (ev.keyboard.keycode == ALLEGRO_KEY_F10)) {
|
||||
double speed = ALLEGRO_BPS_TO_SECS(al_get_timer_speed(game._priv.timer)); // inverting
|
||||
game->_priv.showconsole = true;
|
||||
PrintConsole(game, "DEBUG: 512 frames skipped...");
|
||||
} else if ((ev.type == ALLEGRO_EVENT_KEY_DOWN) && (game->config.debug) && (ev.keyboard.keycode == ALLEGRO_KEY_F10)) {
|
||||
double speed = ALLEGRO_BPS_TO_SECS(al_get_timer_speed(game->_priv.timer)); // inverting
|
||||
speed -= 10;
|
||||
if (speed<10) speed = 10;
|
||||
al_set_timer_speed(game._priv.timer, ALLEGRO_BPS_TO_SECS(speed));
|
||||
game._priv.showconsole = true;
|
||||
PrintConsole(&game, "DEBUG: Gameplay speed: %.2fx", speed/60.0);
|
||||
} else if ((ev.type == ALLEGRO_EVENT_KEY_DOWN) && (game.config.debug) && (ev.keyboard.keycode == ALLEGRO_KEY_F11)) {
|
||||
double speed = ALLEGRO_BPS_TO_SECS(al_get_timer_speed(game._priv.timer)); // inverting
|
||||
al_set_timer_speed(game->_priv.timer, ALLEGRO_BPS_TO_SECS(speed));
|
||||
game->_priv.showconsole = true;
|
||||
PrintConsole(game, "DEBUG: Gameplay speed: %.2fx", speed/60.0);
|
||||
} else if ((ev.type == ALLEGRO_EVENT_KEY_DOWN) && (game->config.debug) && (ev.keyboard.keycode == ALLEGRO_KEY_F11)) {
|
||||
double speed = ALLEGRO_BPS_TO_SECS(al_get_timer_speed(game->_priv.timer)); // inverting
|
||||
speed += 10;
|
||||
if (speed>600) speed = 600;
|
||||
al_set_timer_speed(game._priv.timer, ALLEGRO_BPS_TO_SECS(speed));
|
||||
game._priv.showconsole = true;
|
||||
PrintConsole(&game, "DEBUG: Gameplay speed: %.2fx", speed/60.0);
|
||||
} else if ((ev.type == ALLEGRO_EVENT_KEY_DOWN) && (game.config.debug) && (ev.keyboard.keycode == ALLEGRO_KEY_F12)) {
|
||||
al_set_timer_speed(game->_priv.timer, ALLEGRO_BPS_TO_SECS(speed));
|
||||
game->_priv.showconsole = true;
|
||||
PrintConsole(game, "DEBUG: Gameplay speed: %.2fx", speed/60.0);
|
||||
} else if ((ev.type == ALLEGRO_EVENT_KEY_DOWN) && (game->config.debug) && (ev.keyboard.keycode == ALLEGRO_KEY_F12)) {
|
||||
ALLEGRO_PATH *path = al_get_standard_path(ALLEGRO_USER_DOCUMENTS_PATH);
|
||||
char filename[255] = { };
|
||||
snprintf(filename, 255, LIBSUPERDERPY_GAMENAME_PRETTY "_%ld_%ld.png", time(NULL), clock());
|
||||
snprintf(filename, 255, "%s_%ld_%ld.png", game->name, time(NULL), clock());
|
||||
al_set_path_filename(path, filename);
|
||||
al_save_bitmap(al_path_cstr(path, ALLEGRO_NATIVE_PATH_SEP), al_get_backbuffer(game.display));
|
||||
PrintConsole(&game, "Screenshot stored in %s", al_path_cstr(path, ALLEGRO_NATIVE_PATH_SEP));
|
||||
al_save_bitmap(al_path_cstr(path, ALLEGRO_NATIVE_PATH_SEP), al_get_backbuffer(game->display));
|
||||
PrintConsole(game, "Screenshot stored in %s", al_path_cstr(path, ALLEGRO_NATIVE_PATH_SEP));
|
||||
al_destroy_path(path);
|
||||
} else {
|
||||
EventGamestates(&game, &ev);
|
||||
EventGamestates(game, &ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
game.shuttingdown = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void libsuperderpy_destroy(struct Game *game) {
|
||||
game->shuttingdown = true;
|
||||
|
||||
// in case of restart
|
||||
struct Gamestate *tmp = game._priv.gamestates;
|
||||
struct Gamestate *tmp = game->_priv.gamestates;
|
||||
while (tmp) {
|
||||
if (tmp->started) {
|
||||
PrintConsole(&game, "Stopping gamestate \"%s\"...", tmp->name);
|
||||
(*tmp->api.Gamestate_Stop)(&game, tmp->data);
|
||||
PrintConsole(game, "Stopping gamestate \"%s\"...", tmp->name);
|
||||
(*tmp->api.Gamestate_Stop)(game, tmp->data);
|
||||
tmp->started = false;
|
||||
}
|
||||
if (tmp->loaded) {
|
||||
PrintConsole(&game, "Unloading gamestate \"%s\"...", tmp->name);
|
||||
(*tmp->api.Gamestate_Unload)(&game, tmp->data);
|
||||
PrintConsole(game, "Unloading gamestate \"%s\"...", tmp->name);
|
||||
(*tmp->api.Gamestate_Unload)(game, tmp->data);
|
||||
dlclose(tmp->handle);
|
||||
tmp->loaded = false;
|
||||
}
|
||||
|
@ -508,26 +498,27 @@ int libsuperderpy(int argc, char **argv){
|
|||
}
|
||||
|
||||
al_clear_to_color(al_map_rgb(0,0,0));
|
||||
PrintConsole(&game, "Shutting down...");
|
||||
DrawConsole(&game);
|
||||
PrintConsole(game, "Shutting down...");
|
||||
DrawConsole(game);
|
||||
al_flip_display();
|
||||
al_rest(0.1);
|
||||
(*game._priv.loading.Unload)(&game, game._priv.loading.data);
|
||||
al_destroy_timer(game._priv.timer);
|
||||
Console_Unload(&game);
|
||||
al_destroy_display(game.display);
|
||||
al_destroy_event_queue(game._priv.event_queue);
|
||||
al_destroy_mixer(game.audio.fx);
|
||||
al_destroy_mixer(game.audio.music);
|
||||
al_destroy_mixer(game.audio.mixer);
|
||||
al_destroy_voice(game.audio.v);
|
||||
(*game->_priv.loading.Unload)(game, game->_priv.loading.data);
|
||||
al_destroy_timer(game->_priv.timer);
|
||||
Console_Unload(game);
|
||||
al_destroy_display(game->display);
|
||||
al_destroy_event_queue(game->_priv.event_queue);
|
||||
al_destroy_mixer(game->audio.fx);
|
||||
al_destroy_mixer(game->audio.music);
|
||||
al_destroy_mixer(game->audio.mixer);
|
||||
al_destroy_voice(game->audio.v);
|
||||
al_uninstall_audio();
|
||||
DeinitConfig(&game);
|
||||
DeinitConfig(game);
|
||||
al_uninstall_system();
|
||||
al_shutdown_ttf_addon();
|
||||
al_shutdown_font_addon();
|
||||
if (game.restart) {
|
||||
return execv(argv[0], argv); // FIXME: on OSX there's chdir called which might break it
|
||||
char** argv = game->argv;
|
||||
free(game);
|
||||
if (game->restart) {
|
||||
execv(argv[0], argv); // FIXME: on OSX there's chdir called which might break it
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -32,6 +32,10 @@
|
|||
#include "timeline.h"
|
||||
#include "utils.h"
|
||||
|
||||
#ifndef LIBSUPERDERPY_DATA_TYPE
|
||||
#define LIBSUPERDERPY_DATA_TYPE void
|
||||
#endif
|
||||
|
||||
struct Gamestate;
|
||||
|
||||
/*! \brief Main struct of the game. */
|
||||
|
@ -94,8 +98,17 @@ struct Game {
|
|||
bool shuttingdown; /*!< If true then shut down of the game is pending. */
|
||||
bool restart; /*!< If true then restart of the game is pending. */
|
||||
|
||||
int argc;
|
||||
char** argv;
|
||||
|
||||
const char* name;
|
||||
|
||||
LIBSUPERDERPY_DATA_TYPE *data;
|
||||
|
||||
};
|
||||
|
||||
int libsuperderpy(int argc, char **argv); /*!< Engine's main loop. */
|
||||
struct Game* libsuperderpy_init(int argc, char **argv, const char* name);
|
||||
int libsuperderpy_run(struct Game* game);
|
||||
void libsuperderpy_destroy(struct Game* game);
|
||||
|
||||
#endif
|
||||
|
|
13
src/utils.c
13
src/utils.c
|
@ -238,13 +238,13 @@ void FatalError(struct Game *game, bool fatal, char* format, ...) {
|
|||
al_set_target_backbuffer(game->display);
|
||||
al_clear_to_color(al_map_rgb(0,0,170));
|
||||
|
||||
char *header = LIBSUPERDERPY_GAMENAME_PRETTY;
|
||||
const char *header = game->name;
|
||||
|
||||
al_draw_filled_rectangle(al_get_display_width(game->display)/2 - al_get_text_width(game->_priv.font_bsod, header)/2 - 4, (int)(al_get_display_height(game->display) * 0.32), 4 + al_get_display_width(game->display)/2 + al_get_text_width(game->_priv.font_bsod, header)/2, (int)(al_get_display_height(game->display) * 0.32) + al_get_font_line_height(game->_priv.font_bsod), al_map_rgb(170,170,170));
|
||||
|
||||
al_draw_text(game->_priv.font_bsod, al_map_rgb(0, 0, 170), al_get_display_width(game->display)/2, (int)(al_get_display_height(game->display) * 0.32), ALLEGRO_ALIGN_CENTRE, header);
|
||||
|
||||
char *header2 = "A fatal exception 0xD3RP has occured at 0028:M00F11NZ in GST SD(01) +";
|
||||
const char *header2 = "A fatal exception 0xD3RP has occured at 0028:M00F11NZ in GST SD(01) +";
|
||||
|
||||
al_draw_text(game->_priv.font_bsod, al_map_rgb(255,255,255), al_get_display_width(game->display)/2, (int)(al_get_display_height(game->display) * 0.32+2*al_get_font_line_height(game->_priv.font_bsod)*1.25), ALLEGRO_ALIGN_CENTRE, header2);
|
||||
al_draw_textf(game->_priv.font_bsod, al_map_rgb(255,255,255), al_get_display_width(game->display)/2 - al_get_text_width(game->_priv.font_bsod, header2)/2, (int)(al_get_display_height(game->display) * 0.32+3*al_get_font_line_height(game->_priv.font_bsod)*1.25), ALLEGRO_ALIGN_LEFT, "%p and system just doesn't know what went wrong.", game);
|
||||
|
@ -298,6 +298,13 @@ void TestPath(char* filename, char* subpath, char** result) {
|
|||
al_destroy_path(path);
|
||||
}
|
||||
|
||||
char* GetGameName(struct Game *game, char* format) {
|
||||
// FIXME: that's not how you program in C!
|
||||
char *result = malloc(sizeof(char)*255);
|
||||
snprintf(result, 255, format, game->name);
|
||||
return result;
|
||||
}
|
||||
|
||||
char* GetDataFilePath(struct Game *game, char* filename) {
|
||||
|
||||
//TODO: support for current game
|
||||
|
@ -320,7 +327,7 @@ char* GetDataFilePath(struct Game *game, char* filename) {
|
|||
}
|
||||
|
||||
TestPath(filename, "data/", &result);
|
||||
TestPath(filename, "../share/" LIBSUPERDERPY_GAMENAME "/data/", &result);
|
||||
TestPath(filename, GetGameName(game, "../share/%s/data/"), &result);
|
||||
|
||||
TestPath(filename, "../data/", &result);
|
||||
#ifdef ALLEGRO_MACOSX
|
||||
|
|
|
@ -58,7 +58,7 @@ ALLEGRO_BITMAP* LoadScaledBitmap(struct Game *game, char* filename, int width, i
|
|||
/*! \brief Finds path for data file. */
|
||||
char* GetDataFilePath(struct Game *game, char* filename);
|
||||
|
||||
char* GetLibFilePath(struct Game *game, char* filename);
|
||||
char* GetGameName(struct Game *game, char* format);
|
||||
|
||||
/*! \brief Print some message on game console.
|
||||
*
|
||||
|
|
Loading…
Add table
Reference in a new issue