static inline void HandleEvent(struct Game* game, ALLEGRO_EVENT* ev) { switch (ev->type) { case ALLEGRO_EVENT_DISPLAY_HALT_DRAWING: PauseExecution(game); al_acknowledge_drawing_halt(game->display); break; case ALLEGRO_EVENT_DISPLAY_RESUME_DRAWING: al_acknowledge_drawing_resume(game->display); ReloadGamestates(game); ResumeExecution(game); break; case ALLEGRO_EVENT_DISPLAY_SWITCH_OUT: if (game->config.autopause) { PrintConsole(game, "Focus lost, autopausing..."); PauseExecution(game); } break; case ALLEGRO_EVENT_DISPLAY_SWITCH_IN: if (game->config.autopause) { if (game->config.debug.enabled && game->config.debug.livereload) { ReloadCode(game); } ResumeExecution(game); } break; case ALLEGRO_EVENT_DISPLAY_RESIZE: PrintConsole(game, "Resize event: %dx%d", ev->display.width, ev->display.height); #ifdef LIBSUPERDERPY_IMGUI ImGui_ImplAllegro5_InvalidateDeviceObjects(); #endif al_acknowledge_resize(game->display); #ifdef LIBSUPERDERPY_IMGUI ImGui_ImplAllegro5_CreateDeviceObjects(); #endif // SetupViewport can be expensive, so don't do it when the resize event is already outdated or doesn't change anything if (((ev->display.width != game->_priv.window_width) || (ev->display.height != game->_priv.window_height)) && (ev->display.width == al_get_display_width(game->display)) && (ev->display.height == al_get_display_height(game->display))) { SetupViewport(game); } break; case ALLEGRO_EVENT_KEY_DOWN: #ifdef ALLEGRO_ANDROID if ((ev->keyboard.keycode == ALLEGRO_KEY_MENU) || (ev->keyboard.keycode == ALLEGRO_KEY_TILDE) || (ev->keyboard.keycode == ALLEGRO_KEY_BACKQUOTE)) { #else if ((ev->keyboard.keycode == ALLEGRO_KEY_TILDE) || (ev->keyboard.keycode == ALLEGRO_KEY_BACKQUOTE)) { #endif game->_priv.showconsole = !game->_priv.showconsole; if ((ev->keyboard.modifiers & ALLEGRO_KEYMOD_CTRL) && (game->config.debug.enabled)) { game->_priv.showtimeline = game->_priv.showconsole; } } if (ev->keyboard.keycode == ALLEGRO_KEY_F12) { DrawGamestates(game); int flags = al_get_new_bitmap_flags(); al_set_new_bitmap_flags(ALLEGRO_MEMORY_BITMAP); ALLEGRO_BITMAP* bitmap = al_create_bitmap(al_get_display_width(game->display), al_get_display_height(game->display)); al_set_new_bitmap_flags(flags); ALLEGRO_BITMAP* target = al_get_target_bitmap(); al_set_target_bitmap(bitmap); al_draw_bitmap(al_get_backbuffer(game->display), 0, 0, 0); al_set_target_bitmap(target); PrintConsole(game, "Screenshot made! Storing..."); struct ScreenshotThreadData* data = malloc(sizeof(struct ScreenshotThreadData)); data->game = game; data->bitmap = bitmap; #ifndef LIBSUPERDERPY_SINGLE_THREAD al_run_detached_thread(ScreenshotThread, data); #else ScreenshotThread(data); #endif } break; default: break; } #ifdef MAEMO5 // on Maemo we get mouse events instead of touch ones, so we'll rewrite them by ourselves if ((ev->type == ALLEGRO_EVENT_MOUSE_AXES) || (ev->type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN) || (ev->type == ALLEGRO_EVENT_MOUSE_BUTTON_UP)) { switch (ev->type) { case ALLEGRO_EVENT_MOUSE_BUTTON_DOWN: ev->type = ALLEGRO_EVENT_TOUCH_BEGIN; break; case ALLEGRO_EVENT_MOUSE_BUTTON_UP: ev->type = ALLEGRO_EVENT_TOUCH_END; break; case ALLEGRO_EVENT_MOUSE_AXES: ev->type = ALLEGRO_EVENT_TOUCH_MOVE; break; default: break; } ALLEGRO_DISPLAY* display = ev->mouse.display; float dx = ev->mouse.dx; float dy = ev->mouse.dy; float x = ev->mouse.x; float y = ev->mouse.y; double timestamp = ev->mouse.timestamp; ev->touch.display = display; ev->touch.dx = dx; ev->touch.dy = dy; ev->touch.id = 0; ev->touch.primary = true; ev->touch.source = (ALLEGRO_TOUCH_INPUT*)al_get_touch_input_event_source(); ev->touch.timestamp = timestamp; ev->touch.x = x; ev->touch.y = y; } #endif } static inline void HandleDebugEvent(struct Game* game, ALLEGRO_EVENT* ev) { switch (ev->type) { case ALLEGRO_EVENT_KEY_DOWN: switch (ev->keyboard.keycode) { case ALLEGRO_KEY_F1: if (!game->_priv.paused) { PauseExecution(game); } else { ReloadCode(game); ResumeExecution(game); } break; case ALLEGRO_KEY_F9: game->_priv.speed = ALLEGRO_BPS_TO_SECS(60.0); game->_priv.showconsole = true; PrintConsole(game, "DEBUG: Gameplay speed: 1.00x"); break; case ALLEGRO_KEY_F10: { double speed = ALLEGRO_BPS_TO_SECS(game->_priv.speed); // inverting speed -= 10; if (speed < 10) { speed = 10; } game->_priv.speed = ALLEGRO_BPS_TO_SECS(speed); game->_priv.showconsole = true; PrintConsole(game, "DEBUG: Gameplay speed: %.2fx", speed / 60.0); } break; case ALLEGRO_KEY_F11: { double speed = ALLEGRO_BPS_TO_SECS(game->_priv.speed); // inverting speed += 10; if (speed > 600) { speed = 600; } game->_priv.speed = ALLEGRO_BPS_TO_SECS(speed); game->_priv.showconsole = true; PrintConsole(game, "DEBUG: Gameplay speed: %.2fx", speed / 60.0); } break; } break; default: break; } } static inline bool MainloopEvents(struct Game* game) { do { ALLEGRO_EVENT ev; if (game->_priv.paused && !IS_EMSCRIPTEN) { // there's no frame flipping when paused, so avoid pointless busylooping al_wait_for_event(game->_priv.event_queue, &ev); } else if (!al_get_next_event(game->_priv.event_queue, &ev)) { break; } #ifdef LIBSUPERDERPY_IMGUI ImGui_ImplAllegro5_ProcessEvent(&ev); switch (ev.type) { case ALLEGRO_EVENT_KEY_CHAR: case ALLEGRO_EVENT_KEY_DOWN: case ALLEGRO_EVENT_KEY_UP: if (igGetIO()->WantCaptureKeyboard) { continue; } break; case ALLEGRO_EVENT_MOUSE_AXES: case ALLEGRO_EVENT_MOUSE_BUTTON_DOWN: case ALLEGRO_EVENT_MOUSE_BUTTON_UP: case ALLEGRO_EVENT_TOUCH_BEGIN: case ALLEGRO_EVENT_TOUCH_CANCEL: case ALLEGRO_EVENT_TOUCH_END: case ALLEGRO_EVENT_TOUCH_MOVE: if (igGetIO()->WantCaptureMouse) { continue; } break; default: break; } #endif if (game->_priv.params.handlers.event) { if ((*game->_priv.params.handlers.event)(game, &ev)) { continue; } } if (ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) { EventGamestates(game, &ev); return false; } HandleEvent(game, &ev); if (game->config.debug.enabled) { HandleDebugEvent(game, &ev); } EventGamestates(game, &ev); } while (!al_is_event_queue_empty(game->_priv.event_queue)); return true; } static inline bool MainloopTick(struct Game* game) { if (game->_priv.paused) { return true; } struct Gamestate* tmp = game->_priv.gamestates; #ifdef __EMSCRIPTEN__ emscripten_pause_main_loop(); #endif game->_priv.loading.to_load = 0; game->_priv.loading.loaded = 0; game->_priv.loading.lock = true; game->loading.progress = 0; // TODO: support gamestate dependences/ordering while (tmp) { if (tmp->pending_stop) { PrintConsole(game, "Stopping gamestate \"%s\"...", tmp->name); game->_priv.current_gamestate = tmp; (*tmp->api->stop)(game, tmp->data); tmp->started = false; tmp->pending_stop = false; PrintConsole(game, "Gamestate \"%s\" stopped successfully.", tmp->name); } if (tmp->pending_load) { game->_priv.loading.to_load++; } tmp = tmp->next; } tmp = game->_priv.gamestates; while (tmp) { if (tmp->pending_unload) { #ifdef __EMSCRIPTEN__ al_detach_voice(game->audio.v); #endif PrintConsole(game, "Unloading gamestate \"%s\"...", tmp->name); tmp->loaded = false; tmp->pending_unload = false; game->_priv.current_gamestate = tmp; (*tmp->api->unload)(game, tmp->data); PrintConsole(game, "Gamestate \"%s\" unloaded successfully.", tmp->name); #ifdef __EMSCRIPTEN__ al_attach_mixer_to_voice(game->audio.mixer, game->audio.v); #endif } if (tmp->pending_load) { #ifdef __EMSCRIPTEN__ al_detach_voice(game->audio.v); #endif if (tmp->show_loading && game->_priv.loading.gamestate->open) { (*game->_priv.loading.gamestate->api->start)(game, game->_priv.loading.gamestate->data); } if (!tmp->api) { if (!OpenGamestate(game, tmp, true) || !LinkGamestate(game, tmp)) { tmp->pending_load = false; tmp->pending_start = false; continue; } } if (tmp->api) { PrintConsole(game, "Loading gamestate \"%s\"...", tmp->name); game->_priv.loading.progress = 0; game->_priv.loading.current = tmp; game->_priv.current_gamestate = tmp; struct GamestateLoadingThreadData data = {.game = game, .gamestate = tmp, .bitmap_flags = al_get_new_bitmap_flags()}; game->_priv.loading.in_progress = true; double time = al_get_time(); game->_priv.loading.time = time; CalculateProgress(game); if (tmp->show_loading) { game->loading.shown = true; DrawGamestates(game); DrawConsole(game); al_flip_display(); #ifdef __EMSCRIPTEN__ emscripten_sleep(0); #endif } #ifndef LIBSUPERDERPY_SINGLE_THREAD al_run_detached_thread(GamestateLoadingThread, &data); while (game->_priv.loading.in_progress) { double delta = al_get_time() - game->_priv.loading.time; game->time += delta; // TODO: ability to disable passing time during loading game->_priv.loading.time += delta; if (game->loading.shown && game->_priv.loading.gamestate->open) { (*game->_priv.loading.gamestate->api->logic)(game, game->_priv.loading.gamestate->data, delta); } DrawGamestates(game); if (game->_priv.texture_sync) { al_convert_memory_bitmaps(); game->_priv.texture_sync = false; al_signal_cond(game->_priv.texture_sync_cond); game->_priv.loading.time = al_get_time(); // TODO: rethink time management during loading } DrawConsole(game); al_flip_display(); if (game->_priv.bsod_sync) { al_set_target_bitmap(NULL); game->_priv.bsod_sync = false; al_signal_cond(game->_priv.bsod_cond); } al_lock_mutex(game->_priv.bsod_mutex); while (game->_priv.in_bsod) { al_wait_cond(game->_priv.bsod_cond, game->_priv.bsod_mutex); } al_unlock_mutex(game->_priv.bsod_mutex); } #else GamestateLoadingThread(&data); DrawGamestates(game); DrawConsole(game); al_flip_display(); #ifdef __EMSCRIPTEN__ emscripten_sleep(0); #endif al_convert_memory_bitmaps(); #endif al_set_new_bitmap_flags(data.bitmap_flags); ReloadShaders(game, false); if (tmp->api->post_load) { PrintConsole(game, "[%s] Post-loading...", tmp->name); tmp->api->post_load(game, tmp->data); } game->_priv.loading.progress++; CalculateProgress(game); PrintConsole(game, "Gamestate \"%s\" loaded successfully in %f seconds.", tmp->name, al_get_time() - time); game->_priv.loading.loaded++; DrawGamestates(game); DrawConsole(game); al_flip_display(); #ifdef __EMSCRIPTEN__ emscripten_sleep(0); #endif tmp->loaded = true; tmp->pending_load = false; } if (tmp->show_loading && game->_priv.loading.gamestate->open) { (*game->_priv.loading.gamestate->api->stop)(game, game->_priv.loading.gamestate->data); } tmp->show_loading = true; game->loading.shown = false; game->_priv.timestamp = al_get_time(); #ifdef __EMSCRIPTEN__ al_attach_mixer_to_voice(game->audio.mixer, game->audio.v); #endif } tmp = tmp->next; }
int main(int argc, char **argv) { ALLEGRO_TIMER *timer; ALLEGRO_EVENT_QUEUE *queue; ALLEGRO_MONITOR_INFO info; const char* bitmap_filename; int w = 640, h = 480; bool done = false; bool need_redraw = true; bool background = false; example.show_help = true; example.hold_bitmap_drawing = false; if (argc > 1) { bitmap_filename = argv[1]; } else { bitmap_filename = "data/mysha256x256.png"; } if (!al_init()) { abort_example("Failed to init Allegro.\n"); } if (!al_init_image_addon()) { abort_example("Failed to init IIO addon.\n"); } al_init_font_addon(); init_platform_specific(); al_get_num_video_adapters(); al_get_monitor_info(0, &info); al_set_new_display_option(ALLEGRO_SUPPORTED_ORIENTATIONS, ALLEGRO_DISPLAY_ORIENTATION_ALL, ALLEGRO_SUGGEST); example.display = al_create_display(w, h); if (!example.display) { abort_example("Error creating display.\n"); } w = al_get_display_width(example.display); h = al_get_display_height(example.display); if (!al_install_keyboard()) { abort_example("Error installing keyboard.\n"); } if (!al_install_mouse()) { abort_example("Error installing mouse.\n"); } al_install_touch_input(); example.font = al_create_builtin_font(); if (!example.font) { abort_example("Error creating builtin font\n"); } example.mysha = al_load_bitmap(bitmap_filename); if (!example.mysha) { abort_example("Error loading %s\n", bitmap_filename); } example.white = al_map_rgb_f(1, 1, 1); example.half_white = al_map_rgba_f(1, 1, 1, 0.5); example.dark = al_map_rgb(15, 15, 15); example.red = al_map_rgb_f(1, 0.2, 0.1); change_size(256); add_sprite(); add_sprite(); timer = al_create_timer(1.0 / FPS); queue = al_create_event_queue(); al_register_event_source(queue, al_get_keyboard_event_source()); al_register_event_source(queue, al_get_mouse_event_source()); al_register_event_source(queue, al_get_timer_event_source(timer)); if (al_install_touch_input()) al_register_event_source(queue, al_get_touch_input_event_source()); al_register_event_source(queue, al_get_display_event_source(example.display)); al_start_timer(timer); while (!done) { float x, y; ALLEGRO_EVENT event; w = al_get_display_width(example.display); h = al_get_display_height(example.display); if (!background && need_redraw && al_is_event_queue_empty(queue)) { double t = -al_get_time(); add_time(); al_clear_to_color(al_map_rgb_f(0, 0, 0)); redraw(); t += al_get_time(); example.direct_speed_measure = t; al_flip_display(); need_redraw = false; } al_wait_for_event(queue, &event); switch (event.type) { case ALLEGRO_EVENT_KEY_CHAR: /* includes repeats */ if (event.keyboard.keycode == ALLEGRO_KEY_ESCAPE) done = true; else if (event.keyboard.keycode == ALLEGRO_KEY_UP) { add_sprites(1); } else if (event.keyboard.keycode == ALLEGRO_KEY_DOWN) { remove_sprites(1); } else if (event.keyboard.keycode == ALLEGRO_KEY_LEFT) { change_size(example.bitmap_size - 1); } else if (event.keyboard.keycode == ALLEGRO_KEY_RIGHT) { change_size(example.bitmap_size + 1); } else if (event.keyboard.keycode == ALLEGRO_KEY_F1) { example.show_help ^= 1; } else if (event.keyboard.keycode == ALLEGRO_KEY_SPACE) { example.use_memory_bitmaps ^= 1; change_size(example.bitmap_size); } else if (event.keyboard.keycode == ALLEGRO_KEY_B) { example.blending++; if (example.blending == 5) example.blending = 0; } else if (event.keyboard.keycode == ALLEGRO_KEY_H) { example.hold_bitmap_drawing ^= 1; } break; case ALLEGRO_EVENT_DISPLAY_CLOSE: done = true; break; case ALLEGRO_EVENT_DISPLAY_HALT_DRAWING: background = true; al_acknowledge_drawing_halt(event.display.source); break; case ALLEGRO_EVENT_DISPLAY_RESUME_DRAWING: background = false; al_acknowledge_drawing_resume(event.display.source); break; case ALLEGRO_EVENT_DISPLAY_RESIZE: al_acknowledge_resize(event.display.source); break; case ALLEGRO_EVENT_TIMER: update(); need_redraw = true; break; case ALLEGRO_EVENT_TOUCH_BEGIN: x = event.touch.x; y = event.touch.y; goto click; case ALLEGRO_EVENT_MOUSE_BUTTON_UP: x = event.mouse.x; y = event.mouse.y; goto click; click: { int fh = al_get_font_line_height(example.font); if (x < fh * 12 && y >= h - fh * 30) { int button = (y - (h - fh * 30)) / (fh * 6); if (button == 0) { example.use_memory_bitmaps ^= 1; change_size(example.bitmap_size); } if (button == 1) { example.blending++; if (example.blending == 5) example.blending = 0; } if (button == 3) { if (x < fh * 6) remove_sprites(example.sprite_count / 2); else add_sprites(example.sprite_count); } if (button == 2) { int s = example.bitmap_size * 2; if (x < fh * 6) s = example.bitmap_size / 2; change_size(s); } if (button == 4) { example.show_help ^= 1; } } break; } } } al_destroy_bitmap(example.bitmap); return 0; }
void SceneManager::defaultBeginEventHandler( ALLEGRO_EVENT*evt ) { m_currentScene->processGuiInputEvent(evt); if(evt->type == ALLEGRO_EVENT_TIMER && evt->timer.source == m_gameTimer) { if(m_transitioning) { m_transitionOpacity -= m_transitionRate; if(m_transitionOpacity <= 0) { m_transitionOpacity = 0; m_transitioning = false; } } m_needsRedraw = true; if(!m_needFirstRender) { m_devices->getAudioManager()->logic(); m_currentScene->sceneLogic(); m_currentScene->processGuiLogic(); m_currentScene->logic(); #ifdef CGE_IPHONE m_keyMan->dequeue(); #endif m_devices->getNetClient()->tick(); if(m_bgExecing) { m_bgTime += (1.0f/60.0f); if(m_bgTime > 25.0f) { #ifdef CGE_IPHONE IAPHandler::getInstance().endBackgroundExecution(this); m_bgexecWasHalted = true; m_devices->getNetClient()->setBGMode(false); m_devices->getNetClient()->destroy(); Sprite::destroyAll(); m_wasSignedIn = m_currentSceneType != LOGIN; #endif } } } if(m_callOnNextLogic) { m_nextLogicFrames++; if(m_nextLogicFrames >= 5) { m_callOnNextLogic = false; m_nextLogicFrames = 0; m_currentScene->sceneReady(); } } } else if(evt->type == ALLEGRO_EVENT_DISPLAY_SWITCH_IN) { m_currentScene->windowGotFocus(); printf("GOT FOCUS\n"); } else if(evt->type == ALLEGRO_EVENT_DISPLAY_SWITCH_OUT) { m_currentScene->windowLostFocus(); printf("LOST FOCUS\n"); } else if(evt->type == ALLEGRO_EVENT_DISPLAY_HALT_DRAWING) { m_canDraw = false; m_wasSignedIn = m_currentSceneType != LOGIN; m_devices->getNetClient()->destroy(); al_acknowledge_drawing_halt(al_get_current_display()); printf("HALT DRAWING\n"); //exit(0); } else if(evt->type == ALLEGRO_EVENT_DISPLAY_RESUME_DRAWING) { m_canDraw = true; m_devices->getNetClient()->regenerate(); al_acknowledge_drawing_resume(al_get_current_display()); m_core->renderLoading(0); al_rest(0.5); if(m_nextScene == NO_SCENE && m_currentScene) { m_currentScene->appHasReturned(m_wasSignedIn); m_wasSignedIn = false; m_appResumed = false; } else if(m_nextScene != NO_SCENE) { m_appResumed = true; } else { m_wasSignedIn = false; m_appResumed = false; } printf("RESUME DRAWING\n"); } else if(evt->type == ALLEGRO_EVENT_DISPLAY_RESIZE) { m_needsResize = true; m_newScreenWidth = evt->display.width; m_newScreenHeight = evt->display.height; sendResizeMessage(m_newScreenWidth,m_newScreenHeight); printf("RESIZE\n"); } else if(evt->type == ALLEGRO_EVENT_DISPLAY_LOST) { printf("DEVICE LOST\n"); } else if(evt->type == ALLEGRO_EVENT_DISPLAY_FOUND) { printf("DEVICE FOUND\n"); } else if(evt->type == ALLEGRO_EVENT_DISPLAY_CONNECTED) { printf("DEVICE CONNECTED\n"); } else if(evt->type == ALLEGRO_EVENT_DISPLAY_DISCONNECTED) { printf("DEVICE DISCONNECTED\n"); } else if(evt->type == ALLEGRO_EVENT_DISPLAY_EXPOSE) { printf("DEVICE EXPOSE\n"); } else if(evt->type == ALLEGRO_EVENT_JOYSTICK_AXIS){ #ifdef CGE_MOBILE if(evt->joystick.axis == 0){ //float joys[3][2] m_accelX = evt->joystick.pos; } else if(evt->joystick.axis == 1) { m_accelY = evt->joystick.pos; } else if(evt->joystick.axis == 2) { m_accelZ = evt->joystick.pos; } if(m_currentScene) m_currentScene->accelerometerChanged(m_accelX, m_accelY, m_accelZ); #endif } else if(m_needsResize) { m_needsResize = false; } }