Pārlūkot izejas kodu

Game manager: sprite loading

SG 1 gadu atpakaļ
vecāks
revīzija
7e2fc4e6da
5 mainītis faili ar 116 papildinājumiem un 43 dzēšanām
  1. 13 17
      game_engine.c
  2. 15 14
      game_engine.h
  3. 71 10
      game_manager.c
  4. 16 1
      game_manager.h
  5. 1 1
      game_manager_i.h

+ 13 - 17
game_engine.c

@@ -25,10 +25,6 @@ struct GameEngine {
     FuriPubSub* input_pubsub;
     FuriThreadId thread_id;
     GameEngineSettings settings;
-};
-
-struct RunningGameEngine {
-    GameEngine* engine;
     float fps;
 };
 
@@ -48,6 +44,7 @@ GameEngine* game_engine_alloc(GameEngineSettings settings) {
     engine->input_pubsub = furi_record_open(RECORD_INPUT_EVENTS);
     engine->thread_id = furi_thread_get_current_id();
     engine->settings = settings;
+    engine->fps = 1.0f;
 
     return engine;
 }
@@ -133,11 +130,6 @@ void game_engine_run(GameEngine* engine) {
     // init fps counter
     uint32_t time_start = DWT->CYCCNT;
 
-    // create running engine
-    RunningGameEngine run = {
-        .engine = engine,
-    };
-
     while(true) {
         uint32_t flags =
             furi_thread_flags_wait(GameThreadFlagMask, FuriFlagWaitAny, FuriWaitForever);
@@ -162,15 +154,15 @@ void game_engine_run(GameEngine* engine) {
             canvas_reset(canvas);
 
             // calculate actual fps
-            run.fps = (float)SystemCoreClock / time_delta;
+            engine->fps = (float)SystemCoreClock / time_delta;
 
             // do the work
-            engine->settings.frame_callback(&run, canvas, input, engine->settings.context);
+            engine->settings.frame_callback(engine, canvas, input, engine->settings.context);
 
             // show fps if needed
             if(engine->settings.show_fps) {
                 canvas_set_color(canvas, ColorXOR);
-                canvas_printf(canvas, 0, 7, "%u", (uint32_t)roundf(run.fps));
+                canvas_printf(canvas, 0, 7, "%u", (uint32_t)roundf(engine->fps));
             }
 
             // and output screen buffer
@@ -202,14 +194,18 @@ void game_engine_run(GameEngine* engine) {
     }
 }
 
-void running_game_engine_stop(RunningGameEngine* run) {
-    furi_thread_flags_set(run->engine->thread_id, GameThreadFlagStop);
+void game_engine_stop(GameEngine* engine) {
+    furi_thread_flags_set(engine->thread_id, GameThreadFlagStop);
 }
 
-float running_game_engine_get_delta_time(RunningGameEngine* engine) {
+float game_engine_get_delta_time(GameEngine* engine) {
     return 1.0f / engine->fps;
 }
 
-float running_game_engine_get_delta_frames(RunningGameEngine* engine) {
-    return engine->fps / engine->engine->settings.target_fps;
+float game_engine_get_delta_frames(GameEngine* engine) {
+    return engine->fps / engine->settings.target_fps;
+}
+
+void game_engine_show_fps_set(GameEngine* engine, bool show_fps) {
+    engine->settings.show_fps = show_fps;
 }

+ 15 - 14
game_engine.h

@@ -23,17 +23,12 @@ typedef struct {
 
 typedef struct GameEngine GameEngine;
 
-typedef struct RunningGameEngine RunningGameEngine;
-
 typedef void (*GameEngineStartCallback)(GameEngine* engine, void* context);
 
 typedef void (*GameEngineStopCallback)(GameEngine* engine, void* context);
 
-typedef void (*GameEngineFrameCallback)(
-    RunningGameEngine* engine,
-    Canvas* canvas,
-    InputState input,
-    void* context);
+typedef void (
+    *GameEngineFrameCallback)(GameEngine* engine, Canvas* canvas, InputState input, void* context);
 
 typedef struct {
     float target_fps; // target fps
@@ -64,22 +59,28 @@ void game_engine_run(GameEngine* engine);
  */
 void game_engine_free(GameEngine* engine);
 
-/** Stop the running Game Engine, will not block execution
- * @param engine RunningGameEngine instance
+/** Stop the Game Engine, will not block execution
+ * @param engine GameEngine instance
  */
-void running_game_engine_stop(RunningGameEngine* engine);
+void game_engine_stop(GameEngine* engine);
 
 /** Get delta time between current and previous frame
- * @param engine RunningGameEngine instance
+ * @param engine GameEngine instance
  * @return float  delta time in seconds
  */
-float running_game_engine_get_delta_time(RunningGameEngine* engine);
+float game_engine_get_delta_time(GameEngine* engine);
 
 /** Get delta frames between current and previous frame
- * @param engine RunningGameEngine instance
+ * @param engine GameEngine instance
  * @return float  delta frames
  */
-float running_game_engine_get_delta_frames(RunningGameEngine* engine);
+float game_engine_get_delta_frames(GameEngine* engine);
+
+/** Enable/disable show fps counter
+ * @param engine GameEngine instance
+ * @param show_fps show fps counter
+ */
+void game_engine_show_fps_set(GameEngine* engine, bool show_fps);
 
 #ifdef __cplusplus
 }

+ 71 - 10
game_manager.c

@@ -2,17 +2,26 @@
 #include "level_i.h"
 #include <furi.h>
 #include <m-list.h>
+#include <storage/storage.h>
+
+typedef struct {
+    Sprite* sprite;
+    FuriString* path;
+} SpriteCache;
 
 LIST_DEF(LevelList, Level*, M_POD_OPLIST);
+LIST_DEF(SpriteCacheList, SpriteCache, M_POD_OPLIST);
 
 struct GameManager {
     LevelList_t levels;
     Level* current_level;
     Level* next_level;
 
-    RunningGameEngine* engine;
+    GameEngine* engine;
     InputState input;
     void* game_context;
+
+    SpriteCacheList_t sprites;
 };
 
 GameManager* game_manager_alloc() {
@@ -23,27 +32,43 @@ GameManager* game_manager_alloc() {
     manager->engine = NULL;
     manager->game_context = NULL;
     memset(&manager->input, 0, sizeof(InputState));
+    SpriteCacheList_init(manager->sprites);
     return manager;
 }
 
 void game_manager_free(GameManager* manager) {
     level_call_stop(manager->current_level);
 
-    LevelList_it_t it;
-    LevelList_it(it, manager->levels);
-    while(!LevelList_end_p(it)) {
-        level_call_free(*LevelList_cref(it));
-        level_free(*LevelList_cref(it));
-        LevelList_next(it);
+    // Free all levels
+    {
+        LevelList_it_t it;
+        LevelList_it(it, manager->levels);
+        while(!LevelList_end_p(it)) {
+            level_call_free(*LevelList_cref(it));
+            level_free(*LevelList_cref(it));
+            LevelList_next(it);
+        }
     }
 
     LevelList_clear(manager->levels);
+
+    // Free all sprites
+    {
+        SpriteCacheList_it_t it;
+        SpriteCacheList_it(it, manager->sprites);
+        while(!SpriteCacheList_end_p(it)) {
+            furi_string_free(SpriteCacheList_cref(it)->path);
+            sprite_free(SpriteCacheList_cref(it)->sprite);
+            SpriteCacheList_next(it);
+        }
+    }
+    SpriteCacheList_clear(manager->sprites);
     free(manager);
 }
 
 Level* game_manager_add_level(GameManager* manager, const LevelBehaviour* behaviour) {
     UNUSED(manager);
-    Level* level = level_alloc(behaviour);
+    Level* level = level_alloc(behaviour, manager);
     LevelList_push_back(manager->levels, level);
     level_call_alloc(level);
     if(!manager->current_level) {
@@ -57,6 +82,11 @@ void game_manager_next_level_set(GameManager* manager, Level* next_level) {
     manager->next_level = next_level;
 }
 
+void game_manager_game_stop(GameManager* manager) {
+    GameEngine* engine = game_manager_engine_get(manager);
+    game_engine_stop(engine);
+}
+
 Level* game_manager_current_level_get(GameManager* manager) {
     return manager->current_level;
 }
@@ -76,7 +106,7 @@ void game_manager_render(GameManager* manager, Canvas* canvas) {
     level_render(manager->current_level, manager, canvas);
 }
 
-void game_manager_engine_set(GameManager* manager, RunningGameEngine* engine) {
+void game_manager_engine_set(GameManager* manager, GameEngine* engine) {
     manager->engine = engine;
 }
 
@@ -88,7 +118,7 @@ void game_manager_game_context_set(GameManager* manager, void* context) {
     manager->game_context = context;
 }
 
-RunningGameEngine* game_manager_engine_get(GameManager* manager) {
+GameEngine* game_manager_engine_get(GameManager* manager) {
     return manager->engine;
 }
 
@@ -98,4 +128,35 @@ InputState game_manager_input_get(GameManager* manager) {
 
 void* game_manager_game_context_get(GameManager* manager) {
     return manager->game_context;
+}
+
+void game_manager_show_fps_set(GameManager* manager, bool show_fps) {
+    GameEngine* engine = game_manager_engine_get(manager);
+    game_engine_show_fps_set(engine, show_fps);
+}
+
+Sprite* game_manager_sprite_load(GameManager* manager, const char* path) {
+    SpriteCacheList_it_t it;
+    SpriteCacheList_it(it, manager->sprites);
+    while(!SpriteCacheList_end_p(it)) {
+        if(furi_string_cmp(SpriteCacheList_cref(it)->path, path) == 0) {
+            return SpriteCacheList_cref(it)->sprite;
+        }
+        SpriteCacheList_next(it);
+    }
+
+    FuriString* path_full = furi_string_alloc_set(APP_ASSETS_PATH("sprites/"));
+    furi_string_cat(path_full, path);
+
+    Sprite* sprite = sprite_alloc(furi_string_get_cstr(path_full));
+    if(sprite) {
+        SpriteCache cache = {
+            .sprite = sprite,
+            .path = furi_string_alloc_set(path),
+        };
+        SpriteCacheList_push_back(manager->sprites, cache);
+    }
+    furi_string_free(path_full);
+
+    return sprite;
 }

+ 16 - 1
game_manager.h

@@ -1,6 +1,7 @@
 #pragma once
 #include "level.h"
 #include "game_engine.h"
+#include "sprite.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -14,12 +15,26 @@ void game_manager_next_level_set(GameManager* manager, Level* level);
 
 Level* game_manager_current_level_get(GameManager* manager);
 
-RunningGameEngine* game_manager_engine_get(GameManager* manager);
+GameEngine* game_manager_engine_get(GameManager* manager);
 
 InputState game_manager_input_get(GameManager* manager);
 
 void* game_manager_game_context_get(GameManager* manager);
 
+void game_manager_game_stop(GameManager* manager);
+
+void game_manager_show_fps_set(GameManager* manager, bool show_fps);
+
+/**
+ * @brief Load a sprite from a file
+ * Sprite will be cached and reused if the same file is loaded again
+ * 
+ * @param manager game manager instance
+ * @param path sprite file path, relative to the game's assets folder
+ * @return Sprite* or NULL if the sprite could not be loaded
+ */
+Sprite* game_manager_sprite_load(GameManager* manager, const char* path);
+
 #ifdef __cplusplus
 }
 #endif

+ 1 - 1
game_manager_i.h

@@ -13,7 +13,7 @@ void game_manager_update(GameManager* manager);
 
 void game_manager_render(GameManager* manager, Canvas* canvas);
 
-void game_manager_engine_set(GameManager* manager, RunningGameEngine* engine);
+void game_manager_engine_set(GameManager* manager, GameEngine* engine);
 
 void game_manager_input_set(GameManager* manager, InputState input);