فهرست منبع

add dynamic level loading

jblanked 1 سال پیش
والد
کامیت
928ac89541
4فایلهای تغییر یافته به همراه65 افزوده شده و 133 حذف شده
  1. 9 13
      game/game.c
  2. 55 109
      game/level.c
  3. 1 9
      game/level.h
  4. 0 2
      game/world.h

+ 9 - 13
game/game.c

@@ -1,6 +1,9 @@
 #include "game.h"
 
 /****** Entities: Player ******/
+Level *level_tree;
+Level *level_town;
+Level *level_generic;
 
 // Forward declaration of player_desc, because it's used in player_spawn function.
 
@@ -67,9 +70,9 @@ static void player_update(Entity *self, GameManager *manager, void *context)
     // switch levels if holding OK
     if (input.held & GameKeyOk)
     {
-        game_manager_next_level_set(manager, game_manager_current_level_get(manager) == level_tree ? level_example : level_tree);
-        furi_delay_ms(500);
-        return;
+        // game_manager_next_level_set(manager, game_manager_current_level_get(manager) == level_tree ? level_town : level_tree);
+        // furi_delay_ms(500);
+        // return;
     }
 
     // Clamp the player's position to stay within world bounds
@@ -136,16 +139,9 @@ static void game_start(GameManager *game_manager, void *ctx)
     // For simplicity, we will just set it to 0.
     GameContext *game_context = ctx;
     game_context->score = 0;
-
-    // load all levels
-    // if (!level_load_all(game_manager))
-    // {
-    //     FURI_LOG_E("Game", "Failed to load levels");
-    //     easy_flipper_dialog("[LEVEL ERROR]", "No level data installed.\n\n\nSettings -> Game ->\nInstall Official Level Pack");
-    //     game_manager_add_level(game_manager, &tree_level);
-    // }
-    level_tree = game_manager_add_level(game_manager, &tree_level);
-    level_example = game_manager_add_level(game_manager, &example_level);
+    level_town = game_manager_add_level(game_manager, generic_level("town_world", 0));
+    level_tree = game_manager_add_level(game_manager, generic_level("tree_world", 1));
+    level_generic = game_manager_add_level(game_manager, generic_level("generic_world", 2));
 }
 
 /*

+ 55 - 109
game/level.c

@@ -1,133 +1,79 @@
 #include <game/level.h>
 
-/****** Level ******/
-
 static void level_start(Level *level, GameManager *manager, void *context)
 {
     UNUSED(manager);
     LevelContext *level_context = context;
     // check if the world exists
-    // if (!world_exists(level_context->id))
-    // {
-    //     FURI_LOG_E("Game", "World does not exist");
-    //     easy_flipper_dialog("[WORLD ERROR]", "No world data installed.\n\n\nSettings -> Game ->\nInstall Official World Pack");
-    //     draw_example_world(level);
-    //     return;
-    // }
+    if (!world_exists(level_context->id))
+    {
+        FURI_LOG_E("Game", "World does not exist");
+        easy_flipper_dialog("[WORLD ERROR]", "No world data installed.\n\n\nSettings -> Game ->\nInstall Official World Pack");
+        draw_town_world(level);
+        return;
+    }
+    // get the world data
+    FuriString *world_data = load_furi_world(level_context->id);
+    if (!world_data)
+    {
+        FURI_LOG_E("Game", "Failed to load world data");
+        draw_town_world(level);
+        return;
+    }
     // draw the world
-    // FuriString *world_data = load_furi_world(level_context->id);
-    // if (!world_data)
-    // {
-    //     FURI_LOG_E("Game", "Failed to load world data");
-    //     draw_example_world(level);
-    //     return;
-    // }
-    // if (!draw_json_world_furi(level, load_furi_world(level_context->id)))
-    // {
-    //     FURI_LOG_E("Game", "World exists but failed to draw.");
-    //     draw_example_world(level);
-    // }
-    // furi_string_free(world_data);
-    if (level_context->index == 0)
-        draw_tree_world(level);
-    else
-        draw_example_world(level);
+    if (!draw_json_world(level, furi_string_get_cstr(world_data)))
+    {
+        FURI_LOG_E("Game", "World exists but failed to draw.");
+        draw_town_world(level);
+    }
+    furi_string_free(world_data);
 }
 
-static void level_alloc_tree_world(Level *level, GameManager *manager, void *context)
+static LevelContext *level_context_generic;
+static LevelContext *level_generic_alloc(const char *id, int index)
 {
-    UNUSED(level);
-    LevelContext *level_context = context;
-    snprintf(level_context->id, sizeof(level_context->id), "tree_world");
-    level_context->index = 0;
-    // Add player entity to the level
-    player_spawn(level, manager);
+    if (!level_context_generic)
+    {
+        level_context_generic = malloc(sizeof(LevelContext));
+    }
+    snprintf(level_context_generic->id, sizeof(level_context_generic->id), "%s", id);
+    level_context_generic->index = index;
+    return level_context_generic;
+}
+static void level_generic_free()
+{
+    if (level_context_generic)
+    {
+        free(level_context_generic);
+        level_context_generic = NULL;
+    }
 }
-static void level_alloc_example_world(Level *level, GameManager *manager, void *context)
+
+static void level_alloc_generic_world(Level *level, GameManager *manager, void *context)
 {
-    UNUSED(level);
+    if (!level_context_generic)
+    {
+        FURI_LOG_E("Game", "Generic level context not set");
+        return;
+    }
     LevelContext *level_context = context;
-    snprintf(level_context->id, sizeof(level_context->id), "example_world");
-    level_context->index = 1;
-    // Add player entity to the level
+    snprintf(level_context->id, sizeof(level_context->id), "%s", level_context_generic->id);
+    level_context->index = level_context_generic->index;
     player_spawn(level, manager);
 }
 
-Level *level_tree;
-Level *level_example;
-
-const LevelBehaviour tree_level = {
-    .alloc = level_alloc_tree_world,      // called once, when level allocated
+// Do NOT touch (this is for dynamic level creation)
+const LevelBehaviour _generic_level = {
+    .alloc = level_alloc_generic_world,   // called once, when level allocated
     .free = NULL,                         // called once, when level freed
     .start = level_start,                 // called when level is changed to this level
     .stop = NULL,                         // called when level is changed from this level
     .context_size = sizeof(LevelContext), // size of level context, will be automatically allocated and freed
 };
-const LevelBehaviour example_level = {
-    .alloc = level_alloc_example_world,
-    .free = NULL,
-    .start = level_start,
-    .stop = NULL,
-    .context_size = sizeof(LevelContext),
-};
-
-void level_alloc_world(Level *level, GameManager *manager, void *context)
-{
-    UNUSED(level);
-    LevelContext *level_context = context;
-    snprintf(level_context->id, sizeof(level_context->id), "%s", level_contexts[level_context->index].id);
-    level_context->index = level_contexts[level_context->index].index;
-    // Add player entity to the level
-    player_spawn(level, manager);
-}
 
-bool level_load_all(GameManager *game_manager)
+const LevelBehaviour *generic_level(const char *id, int index)
 {
-    char file_path[128];
-    snprintf(
-        file_path,
-        sizeof(file_path),
-        STORAGE_EXT_PATH_PREFIX "/apps_data/flip_world/worlds/world_list.json");
-
-    FuriString *world_list = flipper_http_load_from_file(file_path);
-    if (!world_list)
-    {
-        FURI_LOG_E(TAG, "Failed to load world list");
-        return false;
-    }
-    for (int i = 0; i < 10; i++)
-    {
-        FuriString *world_id = get_json_array_value_furi("names", i, world_list);
-        if (!world_id)
-        {
-            FURI_LOG_E(TAG, "Failed to get world id");
-            break;
-        }
-        snprintf(level_contexts[i].id, sizeof(level_contexts[i].id), "%s", furi_string_get_cstr(world_id));
-        level_contexts[i].index = i;
-        LevelBehaviour *new_behavior = malloc(sizeof(LevelBehaviour));
-        if (!new_behavior)
-        {
-            FURI_LOG_E(TAG, "Failed to allocate memory for level behavior");
-            furi_string_free(world_id);
-            furi_string_free(world_list);
-            return false;
-        }
-        *new_behavior = (LevelBehaviour){
-            .alloc = level_alloc_world,
-            .free = NULL,
-            .start = level_start,
-            .stop = NULL,
-            .context_size = sizeof(LevelContext),
-        };
-        level_count++;
-        game_manager_add_level(game_manager, new_behavior);
-        furi_string_free(world_id);
-    }
-    furi_string_free(world_list);
-    return true;
-}
-
-LevelContext level_contexts[] = {0};
-Level *levels[] = {0};
-int level_count = 0;
+    level_generic_free();
+    level_context_generic = level_generic_alloc(id, index);
+    return &_generic_level;
+}

+ 1 - 9
game/level.h

@@ -7,12 +7,4 @@ typedef struct
     int index;
 } LevelContext;
 
-extern Level *level_tree;
-extern const LevelBehaviour tree_level;
-extern Level *level_example;
-extern const LevelBehaviour example_level;
-extern LevelContext level_contexts[];
-extern Level *levels[];
-extern int level_count;
-
-bool level_load_all(GameManager *game_manager);
+const LevelBehaviour *generic_level(const char *id, int index);

+ 0 - 2
game/world.h

@@ -11,8 +11,6 @@
 // Maximum number of world objects
 #define MAX_WORLD_OBJECTS 100
 
-// Maximum number of world tokens
-#define MAX_WORLD_TOKENS 1024
 void draw_bounds(Canvas *canvas);
 void draw_example_world(Level *level);
 void draw_tree_world(Level *level);