Kaynağa Gözat

fixes + icon on world switch + choose weapon

- pr3's icon on world switch
- choose player weapon in User settings
- bump menu to 0.4
- rotate levels
jblanked 1 yıl önce
ebeveyn
işleme
6edb6f6d51
7 değiştirilmiş dosya ile 109 ekleme ve 26 silme
  1. 40 10
      callback/callback.c
  2. 2 0
      flip_world.c
  3. 5 2
      flip_world.h
  4. 10 0
      game/enemy.c
  5. 15 2
      game/level.c
  6. 36 12
      game/player.c
  7. 1 0
      game/player.h

+ 40 - 10
callback/callback.c

@@ -160,6 +160,7 @@ static void user_settings_item_selected(void *context, uint32_t index);
 static void screen_on_change(VariableItem *item);
 static void sound_on_change(VariableItem *item);
 static void vibration_on_change(VariableItem *item);
+static void player_on_change(VariableItem *item);
 
 uint32_t callback_to_submenu(void *context)
 {
@@ -357,6 +358,12 @@ static bool alloc_variable_item_list(void *context, uint32_t view_id)
                 app->variable_item_game_download_world = variable_item_list_add(app->variable_item_list, "Install Official World Pack", 0, NULL, NULL);
                 variable_item_set_current_value_text(app->variable_item_game_download_world, "");
             }
+            if (!app->variable_item_game_player_sprite)
+            {
+                app->variable_item_game_player_sprite = variable_item_list_add(app->variable_item_list, "Weapon", 4, player_on_change, NULL);
+                variable_item_set_current_value_index(app->variable_item_game_player_sprite, 1);
+                variable_item_set_current_value_text(app->variable_item_game_player_sprite, game_player_sprite_choices[1]);
+            }
             if (!app->variable_item_game_fps)
             {
                 app->variable_item_game_fps = variable_item_list_add(app->variable_item_list, "FPS", 4, fps_change, NULL);
@@ -381,6 +388,18 @@ static bool alloc_variable_item_list(void *context, uint32_t view_id)
                 variable_item_set_current_value_index(app->variable_item_game_vibration_on, 0);
                 variable_item_set_current_value_text(app->variable_item_game_vibration_on, yes_or_no_choices[0]);
             }
+            char _game_player_sprite[8];
+            if (load_char("Game-Player-Sprite", _game_player_sprite, sizeof(_game_player_sprite)))
+            {
+                int index = strcmp(_game_player_sprite, "naked") == 0 ? 0 : strcmp(_game_player_sprite, "sword") == 0 ? 1
+                                                                        : strcmp(_game_player_sprite, "axe") == 0     ? 2
+                                                                        : strcmp(_game_player_sprite, "bow") == 0     ? 3
+                                                                                                                      : 0;
+                variable_item_set_current_value_index(app->variable_item_game_player_sprite, index);
+                variable_item_set_current_value_text(
+                    app->variable_item_game_player_sprite,
+                    strcmp(game_player_sprite_choices[index], "naked") == 0 ? "None" : game_player_sprite_choices[index]);
+            }
             char _game_fps[8];
             if (load_char("Game-FPS", _game_fps, sizeof(_game_fps)))
             {
@@ -581,6 +600,11 @@ static void free_variable_item_list(void *context)
         free(app->variable_item_game_vibration_on);
         app->variable_item_game_vibration_on = NULL;
     }
+    if (app->variable_item_game_player_sprite)
+    {
+        free(app->variable_item_game_player_sprite);
+        app->variable_item_game_player_sprite = NULL;
+    }
     if (app->variable_item_user_username)
     {
         free(app->variable_item_user_username);
@@ -1383,8 +1407,6 @@ static void fps_change(VariableItem *item)
     game_fps_index = index;
     variable_item_set_current_value_text(item, game_fps_choices[index]);
     variable_item_set_current_value_index(item, index);
-
-    // save the fps
     save_char("Game-FPS", game_fps_choices[index]);
 }
 static void screen_on_change(VariableItem *item)
@@ -1393,8 +1415,6 @@ static void screen_on_change(VariableItem *item)
     game_screen_always_on_index = index;
     variable_item_set_current_value_text(item, yes_or_no_choices[index]);
     variable_item_set_current_value_index(item, index);
-
-    // save the screen always on
     save_char("Game-Screen-Always-On", yes_or_no_choices[index]);
 }
 static void sound_on_change(VariableItem *item)
@@ -1403,8 +1423,6 @@ static void sound_on_change(VariableItem *item)
     game_sound_on_index = index;
     variable_item_set_current_value_text(item, yes_or_no_choices[index]);
     variable_item_set_current_value_index(item, index);
-
-    // save the screen always on
     save_char("Game-Sound-On", yes_or_no_choices[index]);
 }
 static void vibration_on_change(VariableItem *item)
@@ -1413,10 +1431,16 @@ static void vibration_on_change(VariableItem *item)
     game_vibration_on_index = index;
     variable_item_set_current_value_text(item, yes_or_no_choices[index]);
     variable_item_set_current_value_index(item, index);
-
-    // save the screen always on
     save_char("Game-Vibration-On", yes_or_no_choices[index]);
 }
+static void player_on_change(VariableItem *item)
+{
+    uint8_t index = variable_item_get_current_value_index(item);
+    game_player_sprite_index = index;
+    variable_item_set_current_value_text(item, strcmp(game_player_sprite_choices[index], "naked") == 0 ? "None" : game_player_sprite_choices[index]);
+    variable_item_set_current_value_index(item, index);
+    save_char("Game-Player-Sprite", game_player_sprite_choices[index]);
+}
 
 static bool _fetch_worlds(DataLoaderModel *model)
 {
@@ -1461,9 +1485,15 @@ static void game_settings_item_selected(void *context, uint32_t index)
     {
     case 0: // Download all world data s one huge json
         switch_to_view_get_worlds(app);
-    case 1: // Change FPS
+    case 1: // Player Sprite
+        break;
+    case 2: // Change FPS
+        break;
+    case 3: // Screen Always On
+        break;
+    case 4: // Sound On
         break;
-    case 2: // Screen Always On
+    case 5: // Vibration On
         break;
     }
 }

+ 2 - 0
flip_world.c

@@ -6,4 +6,6 @@ char *yes_or_no_choices[] = {"No", "Yes"};
 int game_screen_always_on_index = 1;
 int game_sound_on_index = 0;
 int game_vibration_on_index = 0;
+char *game_player_sprite_choices[] = {"naked", "sword", "axe", "bow"};
+int game_player_sprite_index = 1;
 bool is_enough_heap(size_t heap_size) { return memmgr_get_free_heap() > (heap_size + 1024); } // 1KB buffer

+ 5 - 2
flip_world.h

@@ -9,8 +9,8 @@
 //
 
 #define TAG "FlipWorld"
-#define VERSION 0.3
-#define VERSION_TAG "FlipWorld v0.3"
+#define VERSION 0.4
+#define VERSION_TAG "FlipWorld v0.4"
 
 // Define the submenu items for our FlipWorld application
 typedef enum
@@ -62,6 +62,7 @@ typedef struct
     VariableItem *variable_item_game_download_world;   // The variable item for Download world
     VariableItem *variable_item_game_sound_on;         // The variable item for Sound on
     VariableItem *variable_item_game_vibration_on;     // The variable item for Vibration on
+    VariableItem *variable_item_game_player_sprite;    // The variable item for Player sprite
     //
     VariableItem *variable_item_user_username; // The variable item for the User username
     VariableItem *variable_item_user_password; // The variable item for the User password
@@ -79,4 +80,6 @@ extern char *yes_or_no_choices[];
 extern int game_screen_always_on_index;
 extern int game_sound_on_index;
 extern int game_vibration_on_index;
+extern char *game_player_sprite_choices[];
+extern int game_player_sprite_index;
 bool is_enough_heap(size_t heap_size);

+ 10 - 0
game/enemy.c

@@ -146,6 +146,16 @@ static void enemy_render(Entity *self, GameManager *manager, Canvas *canvas, voi
     // draw player username from GameContext
     Vector posi = entity_pos_get(game_context->player);
     draw_username(canvas, posi, game_context->player_context->username);
+
+    if (game_context->is_switching_level)
+    {
+        // draw switch world icon
+        canvas_draw_icon(
+            canvas,
+            0,
+            0,
+            &I_icon_world_change_128x64px);
+    }
 }
 
 static void send_attack_notification(GameContext *game_context, EnemyContext *enemy_context, bool player_attacked)

+ 15 - 2
game/level.c

@@ -98,9 +98,16 @@ static void set_world(Level *level, GameManager *manager, char *id)
 }
 static void level_start(Level *level, GameManager *manager, void *context)
 {
-    if (!level || !context || !manager)
+    if (!manager)
+    {
+        FURI_LOG_E("Game", "Manager is NULL");
+        return;
+    }
+    GameContext *game_context = game_manager_game_context_get(manager);
+    if (!level || !context)
     {
         FURI_LOG_E("Game", "Level, context, or manager is NULL");
+        game_context->is_switching_level = false;
         return;
     }
 
@@ -111,6 +118,7 @@ static void level_start(Level *level, GameManager *manager, void *context)
     if (!level_context)
     {
         FURI_LOG_E("Game", "Level context is NULL");
+        game_context->is_switching_level = false;
         return;
     }
 
@@ -123,19 +131,24 @@ static void level_start(Level *level, GameManager *manager, void *context)
         {
             FURI_LOG_E("Game", "Failed to fetch world data");
             draw_town_world(level);
+            game_context->is_switching_level = false;
+            furi_delay_ms(1000);
             return;
         }
         furi_string_free(world_data);
 
         set_world(level, manager, level_context->id);
-
         FURI_LOG_I("Game", "World set.");
+        furi_delay_ms(1000);
+        game_context->is_switching_level = false;
     }
     else
     {
         FURI_LOG_I("Game", "World exists.. loading now");
         set_world(level, manager, level_context->id);
         FURI_LOG_I("Game", "World set.");
+        furi_delay_ms(1000);
+        game_context->is_switching_level = false;
     }
 }
 

+ 36 - 12
game/player.c

@@ -9,6 +9,20 @@ static Level *get_next_level(GameManager *manager)
         FURI_LOG_E(TAG, "Failed to get game context");
         return NULL;
     }
+    // check if there are more levels to load
+    if (game_context->current_level + 1 >= game_context->level_count)
+    {
+        game_context->current_level = 0;
+        if (!game_context->levels[game_context->current_level])
+        {
+            if (!allocate_level(manager, game_context->current_level))
+            {
+                FURI_LOG_E(TAG, "Failed to allocate level %d", game_context->current_level);
+                return NULL;
+            }
+        }
+        return game_context->levels[game_context->current_level];
+    }
     for (int i = game_context->current_level + 1; i < game_context->level_count; i++)
     {
         if (!game_context->levels[i])
@@ -62,14 +76,21 @@ void player_spawn(Level *level, GameManager *manager)
         return;
     }
 
+    SpriteContext *sprite_context = get_sprite_context(game_player_sprite_choices[game_player_sprite_index]);
+    if (!sprite_context)
+    {
+        FURI_LOG_E(TAG, "Failed to get sprite context");
+        return;
+    }
+
     // player context must be set each level or NULL pointer will be dereferenced
     if (!load_player_context(player_context))
     {
         FURI_LOG_E(TAG, "Loading player context failed. Initializing default values.");
 
         // Initialize default player context
-        player_context->sprite_right = game_manager_sprite_load(manager, "player_right_sword_15x11px.fxbm");
-        player_context->sprite_left = game_manager_sprite_load(manager, "player_left_sword_15x11px.fxbm");
+        player_context->sprite_right = game_manager_sprite_load(manager, sprite_context->right_file_name);
+        player_context->sprite_left = game_manager_sprite_load(manager, sprite_context->left_file_name);
         player_context->direction = PLAYER_RIGHT; // default direction
         player_context->health = 100;
         player_context->strength = 10;
@@ -85,8 +106,12 @@ void player_spawn(Level *level, GameManager *manager)
         // Set player username
         if (!load_char("Flip-Social-Username", player_context->username, sizeof(player_context->username)))
         {
-            // If loading username fails, default to "Player"
-            snprintf(player_context->username, sizeof(player_context->username), "Player");
+            // check if data/player/username
+            if (!load_char("player/username", player_context->username, sizeof(player_context->username)))
+            {
+                // If loading username fails, default to "Player"
+                snprintf(player_context->username, sizeof(player_context->username), "Player");
+            }
         }
 
         game_context->player_context = player_context;
@@ -101,8 +126,8 @@ void player_spawn(Level *level, GameManager *manager)
     }
 
     // Load player sprite (we'll add this to the JSON later when players can choose their sprite)
-    player_context->sprite_right = game_manager_sprite_load(manager, "player_right_sword_15x11px.fxbm");
-    player_context->sprite_left = game_manager_sprite_load(manager, "player_left_sword_15x11px.fxbm");
+    player_context->sprite_right = game_manager_sprite_load(manager, sprite_context->right_file_name);
+    player_context->sprite_left = game_manager_sprite_load(manager, sprite_context->left_file_name);
 
     player_context->start_position = entity_pos_get(game_context->player);
 
@@ -269,15 +294,14 @@ static void player_update(Entity *self, GameManager *manager, void *context)
     {
         // if all enemies are dead, allow the "OK" button to switch levels
         // otherwise the "OK" button will be used to attack
-        if (game_context->enemy_count == 0)
+        if (game_context->enemy_count == 0 && !game_context->is_switching_level)
         {
-            FURI_LOG_I(TAG, "Switching levels");
+            game_context->is_switching_level = true;
             save_player_context(player);
             game_manager_next_level_set(manager, get_next_level(manager));
-            furi_delay_ms(500);
             return;
         }
-        else
+        else if (game_context->enemy_count > 0)
         {
             game_context->user_input = GameKeyOk;
             // furi_delay_ms(100);
@@ -306,9 +330,9 @@ static void player_update(Entity *self, GameManager *manager, void *context)
 
 static void player_render(Entity *self, GameManager *manager, Canvas *canvas, void *context)
 {
-    UNUSED(manager);
-    if (!self || !context || !canvas)
+    if (!self || !context || !canvas || !manager)
         return;
+
     // Get player context
     PlayerContext *player = context;
 

+ 1 - 0
game/player.h

@@ -60,6 +60,7 @@ typedef struct
     bool ended_early;
     Imu *imu;
     bool imu_present;
+    bool is_switching_level;
 } GameContext;
 
 typedef struct