Przeglądaj źródła

new story mode (tutorial -> story -> pve)

jblanked 8 miesięcy temu
rodzic
commit
bb78acc846
13 zmienionych plików z 115 dodań i 79 usunięć
  1. 2 2
      callback/alloc.c
  2. 2 2
      callback/callback.c
  3. 1 1
      game/draw.c
  4. 4 5
      game/enemy.c
  5. 10 1
      game/game.c
  6. 1 0
      game/game.h
  7. 1 1
      game/npc.c
  8. 11 61
      game/player.c
  9. 4 4
      game/player.h
  10. 2 2
      game/storage.c
  11. 2 0
      game/storage.h
  12. 70 0
      game/story.c
  13. 5 0
      game/story.h

+ 2 - 2
callback/alloc.c

@@ -390,9 +390,9 @@ bool alloc_game_submenu(void *context)
         {
             return false;
         }
-        submenu_add_item(app->submenu_game, "Tutorial", FlipWorldSubmenuIndexTutorial, callback_submenu_choices, app);
-        submenu_add_item(app->submenu_game, "PvP", FlipWorldSubmenuIndexPvP, callback_submenu_choices, app);
+        submenu_add_item(app->submenu_game, "Story", FlipWorldSubmenuIndexStory, callback_submenu_choices, app);
         submenu_add_item(app->submenu_game, "PvE", FlipWorldSubmenuIndexPvE, callback_submenu_choices, app);
+        submenu_add_item(app->submenu_game, "PvP", FlipWorldSubmenuIndexPvP, callback_submenu_choices, app);
     }
     return true;
 }

+ 2 - 2
callback/callback.c

@@ -81,8 +81,8 @@ void callback_submenu_choices(void *context, uint32_t index)
         }
         view_dispatcher_switch_to_view(app->view_dispatcher, FlipWorldViewGameSubmenu);
         break;
-    case FlipWorldSubmenuIndexTutorial:
-        game_mode_index = 2; // GAME_MODE_TUTORIAL
+    case FlipWorldSubmenuIndexStory:
+        game_mode_index = 2; // GAME_MODE_STORY
         game_run(app);
         break;
     case FlipWorldSubmenuIndexPvP:

+ 1 - 1
game/draw.c

@@ -58,7 +58,7 @@ static void draw_menu(GameManager *manager, Canvas *canvas)
         0,
         &I_icon_menu_128x64px);
 
-    if (game_context->game_mode == GAME_MODE_TUTORIAL)
+    if (game_context->game_mode == GAME_MODE_STORY && game_context->story_step < STORY_TUTORIAL_STEPS)
     {
         canvas_set_font(canvas, FontPrimary);
         canvas_draw_str(canvas, 45, 15, "Tutorial");

+ 4 - 5
game/enemy.c

@@ -136,9 +136,8 @@ static void enemy_render(Entity *self, GameManager *manager, Canvas *canvas, voi
     }
 
     // no enemies in story mode for now
-    if (game_context->game_mode != GAME_MODE_TUTORIAL || (game_context->game_mode == GAME_MODE_TUTORIAL && game_context->tutorial_step == 4))
+    if (game_context->game_mode != GAME_MODE_STORY || (game_context->story_step == 4 || game_context->story_step >= STORY_TUTORIAL_STEPS))
     {
-
         // Draw enemy sprite relative to camera, centered on the enemy's position
         canvas_draw_sprite(
             canvas,
@@ -227,7 +226,7 @@ static void enemy_collision(Entity *self, Entity *other, GameManager *manager, v
     GameContext *game_context = game_manager_game_context_get(manager);
     furi_check(game_context, "Enemy collision: GameContext is NULL");
     PlayerContext *player_context = entity_context_get(game_context->player);
-    if (game_context->game_mode == GAME_MODE_TUTORIAL && game_context->tutorial_step != 4)
+    if (game_context->game_mode == GAME_MODE_STORY && game_context->story_step != 4 && game_context->story_step < STORY_TUTORIAL_STEPS)
     {
         // FURI_LOG_I("Game", "Enemy collision: No enemies in story mode");
         return;
@@ -265,10 +264,10 @@ static void enemy_collision(Entity *self, Entity *other, GameManager *manager, v
         // Handle Player Attacking Enemy (Press OK, facing enemy, and enemy not facing player)
         if (player_is_facing_enemy && game_context->last_button == GameKeyOk && !enemy_is_facing_player)
         {
-            if (game_context->game_mode == GAME_MODE_TUTORIAL && game_context->tutorial_step == 4)
+            if (game_context->game_mode == GAME_MODE_STORY && game_context->story_step == 4)
             {
                 // FURI_LOG_I("Game", "Player attacked enemy '%d'!", enemy_context->id);
-                game_context->tutorial_step++;
+                game_context->story_step++;
             }
             // Reset last button
             game_context->last_button = -1;

+ 10 - 1
game/game.c

@@ -87,8 +87,13 @@ static void game_start(GameManager *game_manager, void *ctx)
                 game_context->level_count++;
         }
     }
-    else if (game_context->game_mode == GAME_MODE_TUTORIAL)
+    else if (game_context->game_mode == GAME_MODE_STORY)
     {
+        if (load_uint32("story_step", &game_context->story_step) == false)
+        {
+            game_context->story_step = 0;
+        }
+
         // show tutorial only for now
         game_context->levels[0] = game_manager_add_level(game_manager, world_training());
         game_context->level_count = 1;
@@ -176,6 +181,10 @@ static void game_stop(void *ctx)
             game_context->ws_info = NULL;
         }
     }
+    else if (game_context->game_mode == GAME_MODE_STORY)
+    {
+        save_uint32("story_step", game_context->story_step);
+    }
 
     if (!game_context->ended_early)
     {

+ 1 - 0
game/game.h

@@ -23,6 +23,7 @@ typedef enum
 #include "flip_world.h"
 #include <game/world.h>
 #include <game/level.h>
+#include <game/story.h>
 #include <game/enemy.h>
 #include <game/player.h>
 #include <game/npc.h>

+ 1 - 1
game/npc.c

@@ -109,7 +109,7 @@ static void npc_render(Entity *self, GameManager *manager, Canvas *canvas, void
         current_sprite = npc_context->sprite_right;
     }
     // no NPCs in story mode for now
-    if (game_context->game_mode != GAME_MODE_TUTORIAL)
+    if (game_context->game_mode != GAME_MODE_STORY && game_context->story_step < STORY_TUTORIAL_STEPS)
     {
         // Draw NPC sprite relative to camera, centered on the NPC's position
         canvas_draw_sprite(

+ 11 - 61
game/player.c

@@ -490,37 +490,37 @@ static void player_update(Entity *self, GameManager *manager, void *context)
     }
 
     // adjust tutorial step
-    if (game_context->game_mode == GAME_MODE_TUTORIAL)
+    if (game_context->game_mode == GAME_MODE_STORY)
     {
-        switch (game_context->tutorial_step)
+        switch (game_context->story_step)
         {
         case 0:
             if (input.held & GameKeyLeft)
-                game_context->tutorial_step++;
+                game_context->story_step++;
             break;
         case 1:
             if (input.held & GameKeyRight)
-                game_context->tutorial_step++;
+                game_context->story_step++;
             break;
         case 2:
             if (input.held & GameKeyUp)
-                game_context->tutorial_step++;
+                game_context->story_step++;
             break;
         case 3:
             if (input.held & GameKeyDown)
-                game_context->tutorial_step++;
+                game_context->story_step++;
             break;
         case 5:
             if (input.held & GameKeyOk && game_context->is_menu_open)
-                game_context->tutorial_step++;
+                game_context->story_step++;
             break;
         case 6:
             if (input.held & GameKeyBack)
-                game_context->tutorial_step++;
+                game_context->story_step++;
             break;
         case 7:
             if (input.held & GameKeyBack)
-                game_context->tutorial_step++;
+                game_context->story_step++;
             break;
         }
     }
@@ -546,51 +546,6 @@ static void player_update(Entity *self, GameManager *manager, void *context)
     player_handle_collision(self, pos, player);
 }
 
-static void player_draw_tutorial(Canvas *canvas, GameManager *manager)
-{
-    GameContext *game_context = game_manager_game_context_get(manager);
-    canvas_set_font(canvas, FontPrimary);
-    canvas_draw_str(canvas, 45, 12, "Tutorial");
-    canvas_set_font_custom(canvas, FONT_SIZE_SMALL);
-    switch (game_context->tutorial_step)
-    {
-    case 0:
-        canvas_draw_str(canvas, 15, 20, "Press LEFT to move left");
-        break;
-    case 1:
-        canvas_draw_str(canvas, 15, 20, "Press RIGHT to move right");
-        break;
-    case 2:
-        canvas_draw_str(canvas, 15, 20, "Press UP to move up");
-        break;
-    case 3:
-        canvas_draw_str(canvas, 15, 20, "Press DOWN to move down");
-        break;
-    case 4:
-        canvas_draw_str(canvas, 0, 20, "Press OK + collide with an enemy to attack");
-        break;
-    case 5:
-        canvas_draw_str(canvas, 15, 20, "Hold OK to open the menu");
-        break;
-    case 6:
-        canvas_draw_str(canvas, 15, 20, "Press BACK to escape the menu");
-        break;
-    case 7:
-        canvas_draw_str(canvas, 15, 20, "Hold BACK to save and exit");
-        break;
-    case 8:
-        // end of tutorial so quit
-        save_char("tutorial_done", "J You BLANKED on this one");
-        game_context->tutorial_step = 0;
-        game_context->is_menu_open = false;
-        game_context->is_switching_level = true;
-        game_manager_game_stop(manager);
-        return;
-    default:
-        break;
-    }
-}
-
 static void player_render(Entity *self, GameManager *manager, Canvas *canvas, void *context)
 {
     if (!self || !context || !canvas || !manager)
@@ -639,14 +594,9 @@ static void player_render(Entity *self, GameManager *manager, Canvas *canvas, vo
     canvas_draw_frame(canvas, -draw_camera_x, -draw_camera_y, WORLD_WIDTH, WORLD_HEIGHT);
 
     // render tutorial
-    if (game_context->game_mode == GAME_MODE_TUTORIAL)
+    if (game_context->game_mode == GAME_MODE_STORY)
     {
-        player_draw_tutorial(canvas, manager);
-
-        if (game_context->is_menu_open)
-        {
-            draw_background_render(canvas, manager);
-        }
+        story_draw(self, canvas, manager);
     }
     else
     {

+ 4 - 4
game/player.h

@@ -81,9 +81,9 @@ typedef enum
 // game modes
 typedef enum
 {
-    GAME_MODE_PVE = 0,      // player(s) vs everyone
-    GAME_MODE_PVP = 1,      // player vs player
-    GAME_MODE_TUTORIAL = 2, // tutorial mode
+    GAME_MODE_PVE = 0,   // player(s) vs everyone
+    GAME_MODE_PVP = 1,   // player vs player
+    GAME_MODE_STORY = 2, // story mode
 } GameMode;
 
 // game ending reasons
@@ -127,7 +127,7 @@ typedef struct
     //
     char message[64];
     //
-    uint8_t tutorial_step;
+    uint32_t story_step;
     //
     FlipperHTTP *fhttp;
     //

+ 2 - 2
game/storage.c

@@ -1,6 +1,6 @@
 #include <game/storage.h>
 
-static bool save_uint32(const char *path_name, uint32_t value)
+bool save_uint32(const char *path_name, uint32_t value)
 {
     char buffer[32];
     snprintf(buffer, sizeof(buffer), "%lu", value);
@@ -621,7 +621,7 @@ static bool load_int8(const char *path_name, int8_t *value)
 }
 
 // Helper function to load a uint32_t
-static bool load_uint32(const char *path_name, uint32_t *value)
+bool load_uint32(const char *path_name, uint32_t *value)
 {
     if (!path_name || !value)
     {

+ 2 - 0
game/storage.h

@@ -4,10 +4,12 @@
 #include <flip_world.h>
 #include <flip_storage/storage.h>
 
+bool save_uint32(const char *path_name, uint32_t value);
 bool save_player_context(PlayerContext *player_context);
 bool save_player_context_api(PlayerContext *player_context, FlipperHTTP *fhttp);
 bool websocket_player_context(PlayerContext *player_context, FlipperHTTP *fhttp);
 bool remove_player_from_lobby(FlipperHTTP *fhttp);
+bool load_uint32(const char *path_name, uint32_t *value);
 bool load_player_context(PlayerContext *player_context);
 bool set_player_context();
 

+ 70 - 0
game/story.c

@@ -0,0 +1,70 @@
+#include <game/story.h>
+#include "game/storage.h"
+
+void story_draw_tutorial(Canvas *canvas, GameManager *manager)
+{
+    GameContext *game_context = game_manager_game_context_get(manager);
+    canvas_set_font(canvas, FontPrimary);
+    canvas_draw_str(canvas, 45, 12, "Tutorial");
+    canvas_set_font_custom(canvas, FONT_SIZE_SMALL);
+    switch (game_context->story_step)
+    {
+    case 0:
+        canvas_draw_str(canvas, 15, 20, "Press LEFT to move left");
+        break;
+    case 1:
+        canvas_draw_str(canvas, 15, 20, "Press RIGHT to move right");
+        break;
+    case 2:
+        canvas_draw_str(canvas, 15, 20, "Press UP to move up");
+        break;
+    case 3:
+        canvas_draw_str(canvas, 15, 20, "Press DOWN to move down");
+        break;
+    case 4:
+        canvas_draw_str(canvas, 0, 20, "Press OK + collide with an enemy to attack");
+        break;
+    case 5:
+        canvas_draw_str(canvas, 15, 20, "Hold OK to open the menu");
+        break;
+    case 6:
+        canvas_draw_str(canvas, 15, 20, "Press BACK to escape the menu");
+        break;
+    case 7:
+        canvas_draw_str(canvas, 15, 20, "Hold BACK to save and exit");
+        break;
+    case 8:
+        save_char("tutorial_done", "J You BLANKED on this one");
+        game_context->story_step++;
+        save_uint32("story_step", game_context->story_step);
+        return;
+    default:
+        break;
+    }
+}
+
+void story_draw(Entity *player, Canvas *canvas, GameManager *manager)
+{
+    if (!player || !canvas || !manager)
+        return;
+
+    // Get game context
+    GameContext *game_context = game_manager_game_context_get(manager);
+    if (!game_context)
+        return;
+
+    // Get player context
+    PlayerContext *player_context = entity_context_get(player);
+    if (!player_context)
+        return;
+
+    // Draw the tutorial or game world
+    if (game_context->story_step < STORY_TUTORIAL_STEPS)
+    {
+        story_draw_tutorial(canvas, manager);
+    }
+    else
+    {
+        draw_background_render(canvas, manager);
+    }
+}

+ 5 - 0
game/story.h

@@ -0,0 +1,5 @@
+#pragma once
+#include <game/game.h>
+#include "flip_world.h"
+#define STORY_TUTORIAL_STEPS 9
+void story_draw(Entity *player, Canvas *canvas, GameManager *manager);