| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114 |
- #include "fgeo.h"
- #include <furi.h>
- #include <gui/gui.h>
- #include <input/input.h>
- #include "clock_timer.h"
- GameEngineSettings game_engine_settings_init() {
- GameEngineSettings settings;
- settings.fps = 60.0f;
- settings.show_fps = false;
- return settings;
- }
- struct GameEngine {
- Gui* gui;
- FuriPubSub* input_pubsub;
- FuriThreadId thread_id;
- GameEngineSettings settings;
- volatile bool running;
- };
- typedef enum {
- GameThreadFlagUpdate = 1 << 0,
- GameThreadFlagStop = 1 << 1,
- } GameThreadFlag;
- #define GameThreadFlagMask (GameThreadFlagUpdate | GameThreadFlagStop)
- static void clock_timer_tick(void* context) {
- GameEngine* engine = context;
- furi_thread_flags_set(engine->thread_id, GameThreadFlagUpdate);
- }
- static void input_events_callback(const void* value, void* context) {
- GameEngine* engine = context;
- const InputEvent* event = value;
- if(event->key == InputKeyBack && event->type == InputTypePress) {
- furi_thread_flags_set(engine->thread_id, GameThreadFlagStop);
- }
- }
- GameEngine* game_engine_alloc(GameEngineSettings settings) {
- GameEngine* engine = malloc(sizeof(GameEngine));
- engine->gui = furi_record_open(RECORD_GUI);
- engine->input_pubsub = furi_record_open(RECORD_INPUT_EVENTS);
- engine->thread_id = furi_thread_get_current_id();
- engine->settings = settings;
- engine->running = false;
- return engine;
- }
- void game_engine_free(GameEngine* engine) {
- furi_record_close(RECORD_GUI);
- furi_record_close(RECORD_INPUT_EVENTS);
- free(engine);
- }
- static void canvas_printf(Canvas* canvas, uint8_t x, uint8_t y, const char* format, ...) {
- FuriString* string = furi_string_alloc();
- va_list args;
- va_start(args, format);
- furi_string_vprintf(string, format, args);
- va_end(args);
- canvas_draw_str(canvas, x, y, furi_string_get_cstr(string));
- furi_string_free(string);
- }
- void game_engine_run(GameEngine* engine) {
- engine->running = true;
- Canvas* canvas = gui_direct_draw_acquire(engine->gui);
- FuriPubSubSubscription* input_subscription =
- furi_pubsub_subscribe(engine->input_pubsub, input_events_callback, engine);
- clock_timer_init(clock_timer_tick, engine, engine->settings.fps);
- clock_timer_start();
- uint32_t time_start = DWT->CYCCNT;
- while(true) {
- uint32_t flags =
- furi_thread_flags_wait(GameThreadFlagMask, FuriFlagWaitAny, FuriWaitForever);
- furi_check((flags & FuriFlagError) == 0);
- if(flags & GameThreadFlagUpdate) {
- canvas_reset(canvas);
- uint32_t time_end = DWT->CYCCNT;
- uint32_t time_delta = time_end - time_start;
- time_start = time_end;
- if(engine->settings.show_fps) {
- float fps = 1.0f / (time_delta / (float)SystemCoreClock);
- canvas_set_color(canvas, ColorXOR);
- canvas_printf(canvas, 0, 7, "%u", (uint32_t)roundf(fps));
- }
- canvas_commit(canvas);
- } else if(flags & GameThreadFlagStop) {
- break;
- }
- }
- clock_timer_stop();
- clock_timer_deinit();
- gui_direct_draw_release(engine->gui);
- furi_pubsub_unsubscribe(engine->input_pubsub, input_subscription);
- engine->running = false;
- }
|