bool System::initSharedSystem() { if (!al_is_system_installed()) { assert(al_init() && "Failed to initialize Allegro."); assert(al_inhibit_screensaver(true) && "Failed to inhibit screensaver."); al_set_new_display_flags(ALLEGRO_WINDOWED | ALLEGRO_GENERATE_EXPOSE_EVENTS | ALLEGRO_OPENGL_FORWARD_COMPATIBLE | ALLEGRO_OPENGL); al_set_new_bitmap_flags(ALLEGRO_VIDEO_BITMAP | ALLEGRO_MIN_LINEAR | ALLEGRO_MAG_LINEAR); } if (!al_init_image_addon()) { std::cerr << "Failed to initialize image addon" << std::endl; return false; } if (!al_install_keyboard()) { std::cerr << "Failed to install keyboard" << std::endl; return false; } if (!al_install_mouse()) { std::cerr << "Failed to install mouse" << std::endl; return false; } if (!al_install_joystick()) { std::cerr << "Failed to install joystick" << std::endl; return false; } return true; }
int main(short int argc, char** argv) { al_init(); al_install_keyboard(); al_install_mouse(); al_init_image_addon(); al_init_font_addon(); al_init_ttf_addon(); ALLEGRO_MONITOR_INFO oMonitorInfo; al_get_monitor_info(0, &oMonitorInfo); short int iDisplayWidth = oMonitorInfo.x2 * 0.70f; short int iDisplayHeight = oMonitorInfo.y2 * 0.70f; short int iAppWidth = iDisplayWidth * 0.95f; short int iAppHeight = iDisplayHeight * 0.95f; short int iMarginHorizontal = (iDisplayWidth - iAppWidth) / 2; short int iMarginVertical = ((iDisplayHeight - iAppHeight) / 2); int iGenerations = 0; short int iFPS = 30; float iLifeMin = 3.0f; float iLifeMax = 37.0f; short int iFontSize = (iDisplayWidth > 1024) ? 12 : 10; if (iDisplayWidth < 800) { iFontSize = 8; } long int iSimulations = 1; std::random_device rd; std::mt19937 mt(rd()); std::uniform_real_distribution<double> dist(iLifeMin, iLifeMax); int iLifeScarcity = std::round(dist(mt)); bool** pCells = new bool*[iAppWidth]; bool** pNextGenCells = new bool*[iAppWidth]; initCells(pCells, pNextGenCells, iAppWidth, iAppHeight, iLifeScarcity); ALLEGRO_DISPLAY* pDisplay = al_create_display(iDisplayWidth, iDisplayHeight); ALLEGRO_EVENT_QUEUE* pQueue = al_create_event_queue(); ALLEGRO_TIMER* pTimer = al_create_timer(1.0f / iFPS); ALLEGRO_TIMER* pSecondBySecondTimer = al_create_timer(1.0f); ALLEGRO_BITMAP* pBuffer = al_create_bitmap(iAppWidth, iAppHeight); ALLEGRO_COLOR oBackgroundColor = al_map_rgb(0, 0, 0); ALLEGRO_COLOR oCellColor = al_map_rgb(randr(150, 255), randr(150, 255), randr(150, 255)); ALLEGRO_FONT* oFont = al_load_ttf_font("VeraMono.ttf", iFontSize, 0); ALLEGRO_FONT* oFontLarge = al_load_ttf_font("VeraMono.ttf", (iFontSize * 3), 0); al_inhibit_screensaver(true); al_register_event_source(pQueue, al_get_keyboard_event_source()); al_register_event_source(pQueue, al_get_mouse_event_source()); al_register_event_source(pQueue, al_get_timer_event_source(pTimer)); al_register_event_source(pQueue, al_get_timer_event_source(pSecondBySecondTimer)); al_set_target_backbuffer(pDisplay); al_clear_to_color(oBackgroundColor); al_flip_display(); al_start_timer(pTimer); al_start_timer(pSecondBySecondTimer); ALLEGRO_EVENT oEvent; short int iBufferUsed = 0; short int iBufferDrawn = 0; bool bRedraw = false; std::string sHeaderStatistics = "GEN [GENXXXXX] FPS [FPSXXXXX] CELLS [CELLSXXXXX] GENS/S [GENSSXXXXX] SCARCTY [SCARXXXXX] TIME [TIMEXXXXX]"; std::string sHeaderStats = ""; /* std::string sHeaderText_2 = ""; std::string sHeaderText_3 = ""; std::string sHeaderText_4 = ""; std::string sHeaderText_5 = ""; std::string sHeaderText_6 = ""; */ std::string sCountdownText = ""; std::string sSimulations = ""; std::string sStats = "CELLS: "; sStats.append(std::to_string((iAppWidth * iAppHeight))); sStats.append(", MAP SIZE (KB): "); sStats.append(std::to_string((iAppWidth * iAppHeight * sizeof(bool)) / 1024)); sStats.append(" (SPACE) Pause (C)olor, (R)eload, (S)carcity, (F) +1 FPS, (G) -1 FPS, (ESC) Exit"); long int iTotalAlive = 0; int iPatternStableBuffer = (iFPS * 4); long int* iTotalPatternStable = new long int[iPatternStableBuffer]; short int iTotalPatternCounter = 0; long int iSecondsRunning = 0; float fPosText2 = (iAppWidth * 0.15); float fPosText3 = (iAppWidth * 0.30); float fPosText4 = (iAppWidth * 0.50); float fPosText5 = (iAppWidth * 0.70); float fPosText6 = (iAppWidth * 0.85); float fPosTextSim = (iAppWidth * 0.75); bool bPatternIsStable = false; int iCountdownSeconds = 10; bool bDrawingOn = false; bool bTimerStopped = false; ALLEGRO_COLOR oRandColor = al_map_rgb(randr(0, 255), randr(0, 255), randr(0, 255)); while (true) { al_wait_for_event(pQueue, &oEvent); if (oEvent.type == ALLEGRO_EVENT_TIMER) { if (!bTimerStopped) { if (oEvent.timer.source == pTimer) { iTotalAlive = 0; redrawCells(pBuffer, pCells, pNextGenCells, iAppWidth, iAppHeight, oCellColor, oBackgroundColor); nextGeneration(pCells, pNextGenCells, iAppWidth, iAppHeight, iTotalAlive); al_set_target_backbuffer(pDisplay); al_clear_to_color(oBackgroundColor); al_draw_bitmap(pBuffer, iMarginHorizontal, iMarginVertical, 0); sHeaderStats = ReplaceString(sHeaderStatistics, "[GENXXXXX]", std::to_string(iGenerations)); sHeaderStats = ReplaceString(sHeaderStats, "[FPSXXXXX]", std::to_string(iFPS)); sHeaderStats = ReplaceString(sHeaderStats, "[CELLSXXXXX]", std::to_string(iTotalAlive)); sHeaderStats = ReplaceString(sHeaderStats, "[SCARXXXXX]", std::to_string(iLifeScarcity)); sHeaderStats = ReplaceString(sHeaderStats, "[TIMEXXXXX]", std::to_string(iSecondsRunning)); if (iGenerations > 0 && iSecondsRunning > 0) { sHeaderStats = ReplaceString(sHeaderStats, "[GENSSXXXXX]", std::to_string(iGenerations / iSecondsRunning)); } else { sHeaderStats = ReplaceString(sHeaderStats, "[GENSSXXXXX]", "0"); } sSimulations = "SIMS "; sSimulations.append(std::to_string(iSimulations)); int iLengthSims = al_get_text_width(oFont, sSimulations.c_str()); int iLengthStats = al_get_text_width(oFont, sHeaderStats.c_str()); al_draw_text(oFont, oCellColor, ((iAppWidth - iLengthStats) / 2), 1.0f, 0, sHeaderStats.c_str()); al_draw_text(oFont, oCellColor, (iDisplayWidth - (iLengthSims + 25.0f)), (iAppHeight + iMarginVertical + 5.0f), 0, sSimulations.c_str()); al_draw_text(oFont, oCellColor, 25.0f, (iAppHeight + iMarginVertical + 5.0f), 0, sStats.c_str()); if (bPatternIsStable == true) { sCountdownText.clear(); sCountdownText.append("PATTERN STABILIZED, RESTARTING IN... "); int iLengthStr = al_get_text_width(oFontLarge, sCountdownText.c_str()); sCountdownText.append(std::to_string(iCountdownSeconds)); al_draw_text(oFontLarge, oRandColor, ((iAppWidth - iLengthStr) / 2), (iAppHeight * 0.45f), 0, sCountdownText.c_str()); } al_flip_display(); ++iGenerations; copyCells(pCells, pNextGenCells, iAppWidth, iAppHeight); if (iTotalPatternCounter == iPatternStableBuffer) { bPatternIsStable = isPatternStable(iTotalPatternStable, iPatternStableBuffer); delete iTotalPatternStable; iTotalPatternStable = new long int[iPatternStableBuffer]; iTotalPatternCounter = 0; } iTotalPatternStable[iTotalPatternCounter] = iTotalAlive; ++iTotalPatternCounter; } if (oEvent.timer.source == pSecondBySecondTimer) { if (bPatternIsStable == true) { if (iCountdownSeconds > 1) { --iCountdownSeconds; } else { bPatternIsStable = false; iTotalPatternCounter = 0; iGenerations = 0; iSecondsRunning = 0; iCountdownSeconds = 10; ++iSimulations; clearCells(pCells, pNextGenCells, iAppWidth, iAppHeight); randomCells(pCells, iAppWidth, iAppHeight, iLifeScarcity); } } else { iCountdownSeconds = 10; } ++iSecondsRunning; oRandColor = al_map_rgb(randr(0, 255), randr(0, 255), randr(0, 255)); } } } if (oEvent.type == ALLEGRO_EVENT_KEY_DOWN) { if (oEvent.keyboard.keycode == ALLEGRO_KEY_ESCAPE) { break; } if (oEvent.keyboard.keycode == ALLEGRO_KEY_SPACE) { if (!bTimerStopped) { bTimerStopped = true; al_stop_timer(pTimer); } else { bTimerStopped = false; al_start_timer(pTimer); } } if (oEvent.keyboard.keycode == ALLEGRO_KEY_R) { bPatternIsStable = false; iTotalPatternCounter = 0; iGenerations = 0; iSecondsRunning = 0; iCountdownSeconds = 10; ++iSimulations; clearCells(pCells, pNextGenCells, iAppWidth, iAppHeight); randomCells(pCells, iAppWidth, iAppHeight, iLifeScarcity); } if (oEvent.keyboard.keycode == ALLEGRO_KEY_S) { bPatternIsStable = false; iTotalPatternCounter = 0; iGenerations = 0; iSecondsRunning = 0; iCountdownSeconds = 10; iLifeScarcity = randr(iLifeMin, iLifeMax); ++iSimulations; clearCells(pCells, pNextGenCells, iAppWidth, iAppHeight); randomCells(pCells, iAppWidth, iAppHeight, iLifeScarcity); } if (oEvent.keyboard.keycode == ALLEGRO_KEY_M) { bPatternIsStable = false; iTotalPatternCounter = 0; iGenerations = 0; iSecondsRunning = 0; iCountdownSeconds = 10; iLifeScarcity = iLifeMin; ++iSimulations; clearCells(pCells, pNextGenCells, iAppWidth, iAppHeight); randomCells(pCells, iAppWidth, iAppHeight, iLifeScarcity); } if (oEvent.keyboard.keycode == ALLEGRO_KEY_N) { bPatternIsStable = false; iTotalPatternCounter = 0; iGenerations = 0; iSecondsRunning = 0; iCountdownSeconds = 10; iLifeScarcity = iLifeMax; ++iSimulations; clearCells(pCells, pNextGenCells, iAppWidth, iAppHeight); randomCells(pCells, iAppWidth, iAppHeight, iLifeScarcity); } if (oEvent.keyboard.keycode == ALLEGRO_KEY_F) { ++iFPS; al_set_timer_speed(pTimer, (1.0f / iFPS)); } if (oEvent.keyboard.keycode == ALLEGRO_KEY_G) { if(iFPS > 3) { --iFPS; } al_set_timer_speed(pTimer, (1.0f / iFPS)); } if (oEvent.keyboard.keycode == ALLEGRO_KEY_C) { int iRCell = randr(0, 255); int iGCell = randr(0, 255); int iBCell = randr(0, 255); oCellColor = al_map_rgb(iRCell, iGCell, iBCell); } } } // End main loop al_destroy_event_queue(pQueue); al_destroy_display(pDisplay); delete iTotalPatternStable; for (short int i = 0; i < iAppWidth; i++) { delete pCells[i]; delete pNextGenCells[i]; } delete[] pCells; delete[] pNextGenCells; return 0; }
VALUE rbal_inhibit_screensaver(VALUE rself, VALUE rinhibit) { return RBH_INT_BOOL(al_inhibit_screensaver(RBH_BOOL_INT(rinhibit))); }
int main(int argc, char **argv){ signal(SIGSEGV, derp); srand(time(NULL)); al_set_org_name("Super Derpy"); al_set_app_name("Back to the Browser Wars"); #ifdef ALLEGRO_MACOSX char exe_path[MAXPATHLEN]; char link_path[MAXPATHLEN]; uint32_t size = sizeof(exe_path); _NSGetExecutablePath(exe_path, &size); realpath(exe_path, link_path); chdir(link_path); #endif if(!al_init()) { fprintf(stderr, "failed to initialize allegro!\n"); return -1; } struct Game 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.font_bsod = NULL; game._priv.console = NULL; game.config.fullscreen = atoi(GetConfigOptionDefault(&game, "SuperDerpy", "fullscreen", "0")); 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; } if(!al_init_acodec_addon()){ fprintf(stderr, "failed to initialize audio codecs!\n"); return -1; } if(!al_install_audio()){ fprintf(stderr, "failed to initialize audio!\n"); return -1; } if(!al_install_keyboard()){ fprintf(stderr, "failed to initialize keyboard!\n"); return -1; } if(!al_init_primitives_addon()){ fprintf(stderr, "failed to initialize primitives!\n"); return -1; } if(!al_install_mouse()) { fprintf(stderr, "failed to initialize the mouse!\n"); return -1; } al_init_font_addon(); if(!al_init_ttf_addon()){ fprintf(stderr, "failed to initialize fonts!\n"); return -1; } 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); #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) { fprintf(stderr, "failed to create display!\n"); return -1; } SetupViewport(&game); PrintConsole(&game, "Viewport %dx%d", game.viewport.width, game.viewport.height); ALLEGRO_BITMAP *icon = al_load_bitmap(GetDataFilePath(&game, "icons/bttbw.png")); al_set_window_title(game.display, "Back to the Browser Wars"); al_set_display_icon(game.display, icon); al_destroy_bitmap(icon); 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.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.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); setlocale(LC_NUMERIC, "C"); game.shuttingdown = false; game.restart = false; game.mediator.lives = 3; game.mediator.score = 0; game.mediator.modificator = 1; game.mediator.heart = CreateCharacter(&game, "heart"); RegisterSpritesheet(&game, game.mediator.heart, "heart"); RegisterSpritesheet(&game, game.mediator.heart, "blank"); LoadSpritesheets(&game, game.mediator.heart); SelectSpritesheet(&game, game.mediator.heart, "heart"); char* gamestate = strdup("dosowisko"); // FIXME: don't hardcore gamestate 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; } LoadGamestate(&game, gamestate); game._priv.gamestates->showLoading = false; // we have only one gamestate right now StartGamestate(&game, gamestate); free(gamestate); char libname[1024] = {}; snprintf(libname, 1024, "libsuperderpy-%s-loading" LIBRARY_EXTENTION, "bttbw"); void *handle = dlopen(libname, RTLD_NOW); if (!handle) { FatalError(&game, true, "Error while initializing loading screen %s", dlerror()); exit(1); } else { #define GS_LOADINGERROR FatalError(&game, true, "Error on resolving loading symbol: %s", dlerror()); exit(1); 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)) { 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); tmp->started = false; tmp->pending_start = false; } if ((tmp->pending_load) && (!tmp->loaded)) toLoad++; tmp=tmp->next; } tmp = game._priv.gamestates; // FIXME: move to function // TODO: support dependences double t = -1; while (tmp) { if ((tmp->pending_load) && (tmp->loaded)) { 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); dlclose(tmp->handle); tmp->handle = NULL; 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); // TODO: take proper game name char libname[1024]; snprintf(libname, 1024, "libsuperderpy-%s-%s" LIBRARY_EXTENTION, "bttbw", 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()); 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; if (!(tmp->api.Gamestate_Draw = dlsym(tmp->handle, "Gamestate_Draw"))) { GS_ERROR; } if (!(tmp->api.Gamestate_Logic = dlsym(tmp->handle, "Gamestate_Logic"))) { GS_ERROR; } if (!(tmp->api.Gamestate_Load = dlsym(tmp->handle, "Gamestate_Load"))) { GS_ERROR; } if (!(tmp->api.Gamestate_Start = dlsym(tmp->handle, "Gamestate_Start"))) { GS_ERROR; } if (!(tmp->api.Gamestate_Pause = dlsym(tmp->handle, "Gamestate_Pause"))) { GS_ERROR; } if (!(tmp->api.Gamestate_Resume = dlsym(tmp->handle, "Gamestate_Resume"))) { GS_ERROR; } if (!(tmp->api.Gamestate_Stop = dlsym(tmp->handle, "Gamestate_Stop"))) { GS_ERROR; } if (!(tmp->api.Gamestate_Unload = dlsym(tmp->handle, "Gamestate_Unload"))) { GS_ERROR; } if (!(tmp->api.Gamestate_ProcessEvent = dlsym(tmp->handle, "Gamestate_ProcessEvent"))) { GS_ERROR; } if (!(tmp->api.Gamestate_Reload = dlsym(tmp->handle, "Gamestate_Reload"))) { GS_ERROR; } if (!(tmp->api.Gamestate_ProgressCount = dlsym(tmp->handle, "Gamestate_ProgressCount"))) { GS_ERROR; } int p = 0; void progress(struct Game *game) { p++; DrawGamestates(game); float progress = ((p / (*(tmp->api.Gamestate_ProgressCount) ? (float)*(tmp->api.Gamestate_ProgressCount) : 1))/(float)toLoad)+(loaded/(float)toLoad); if (game->config.debug) PrintConsole(game, "[%s] Progress: %d% (%d/%d)", tmp->name, (int)(progress*100), p, *(tmp->api.Gamestate_ProgressCount)); if (tmp->showLoading) (*game->_priv.loading.Draw)(game, game->_priv.loading.data, progress); DrawConsole(game); if (al_get_time() - t >= 1/60.0) { al_flip_display(); } t = al_get_time(); } t = al_get_time(); // initially draw loading screen with empty bar DrawGamestates(&game); if (tmp->showLoading) { (*game._priv.loading.Draw)(&game, game._priv.loading.data, loaded/(float)toLoad); } 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 loaded++; tmp->loaded = true; tmp->pending_load = false; } al_start_timer(game._priv.timer); } tmp=tmp->next; } bool gameActive = false; 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); tmp->started = true; tmp->pending_start = false; } if ((tmp->started) || (tmp->pending_start) || (tmp->pending_load)) gameActive = true; tmp=tmp->next; } if (!gameActive) { PrintConsole(&game, "No gamestates left, exiting..."); break; } DrawGamestates(&game); DrawConsole(&game); al_flip_display(); redraw = false; } else {