story.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. #include <game/story.h>
  2. #include <game/storage.h>
  3. #include <flip_storage/storage.h>
  4. #include <game/level.h>
  5. void story_draw_tutorial(Canvas *canvas, GameManager *manager)
  6. {
  7. GameContext *game_context = game_manager_game_context_get(manager);
  8. furi_check(game_context);
  9. canvas_set_font(canvas, FontPrimary);
  10. canvas_draw_str(canvas, 45, 12, "Tutorial");
  11. canvas_set_font_custom(canvas, FONT_SIZE_SMALL);
  12. switch (game_context->story_step)
  13. {
  14. case 0:
  15. canvas_draw_str(canvas, 15, 20, "Press LEFT to move left");
  16. break;
  17. case 1:
  18. canvas_draw_str(canvas, 15, 20, "Press RIGHT to move right");
  19. break;
  20. case 2:
  21. canvas_draw_str(canvas, 15, 20, "Press UP to move up");
  22. break;
  23. case 3:
  24. canvas_draw_str(canvas, 15, 20, "Press DOWN to move down");
  25. break;
  26. case 4:
  27. canvas_draw_str(canvas, 0, 20, "Press OK + collide with an enemy to attack");
  28. break;
  29. case 5:
  30. canvas_draw_str(canvas, 15, 20, "Hold OK to open the menu");
  31. break;
  32. case 6:
  33. canvas_draw_str(canvas, 15, 20, "Press BACK to escape the menu");
  34. break;
  35. case 7:
  36. canvas_draw_str(canvas, 15, 20, "Hold BACK to save and exit");
  37. break;
  38. case 8:
  39. save_char("tutorial_done", "J You BLANKED on this one");
  40. game_context->story_step++;
  41. save_uint32("story_step", game_context->story_step);
  42. return;
  43. default:
  44. break;
  45. }
  46. }
  47. void story_draw(Entity *player, Canvas *canvas, GameManager *manager)
  48. {
  49. if (!player || !canvas || !manager)
  50. return;
  51. // Get game context
  52. GameContext *game_context = game_manager_game_context_get(manager);
  53. furi_check(game_context);
  54. // Draw the tutorial or game world
  55. if (game_context->story_step < STORY_TUTORIAL_STEPS)
  56. {
  57. story_draw_tutorial(canvas, manager);
  58. }
  59. else
  60. {
  61. draw_background_render(canvas, manager);
  62. }
  63. }
  64. void story_update(Entity *player, GameManager *manager)
  65. {
  66. UNUSED(player);
  67. GameContext *game_context = game_manager_game_context_get(manager);
  68. furi_check(game_context);
  69. InputState input = game_manager_input_get(manager);
  70. if (game_context->game_mode == GAME_MODE_STORY)
  71. {
  72. switch (game_context->story_step)
  73. {
  74. case 0:
  75. if (input.held & GameKeyLeft)
  76. game_context->story_step++;
  77. break;
  78. case 1:
  79. if (input.held & GameKeyRight)
  80. game_context->story_step++;
  81. break;
  82. case 2:
  83. if (input.held & GameKeyUp)
  84. game_context->story_step++;
  85. break;
  86. case 3:
  87. if (input.held & GameKeyDown)
  88. game_context->story_step++;
  89. break;
  90. case 5:
  91. if (input.held & GameKeyOk && game_context->is_menu_open)
  92. game_context->story_step++;
  93. break;
  94. case 6:
  95. if (input.held & GameKeyBack)
  96. game_context->story_step++;
  97. break;
  98. case 7:
  99. if (input.held & GameKeyBack)
  100. game_context->story_step++;
  101. break;
  102. }
  103. }
  104. }
  105. static void story_draw_world(Level *level, GameManager *manager, void *context)
  106. {
  107. UNUSED(context);
  108. if (!manager || !level)
  109. {
  110. FURI_LOG_E("Game", "Manager or level is NULL");
  111. return;
  112. }
  113. GameContext *game_context = game_manager_game_context_get(manager);
  114. level_clear(level);
  115. FuriString *json_data_str = furi_string_alloc();
  116. furi_string_cat_str(json_data_str, "{\"name\":\"story_world_v8\",\"author\":\"ChatGPT\",\"json_data\":[{\"i\":\"rock_medium\",\"x\":100,\"y\":100,\"a\":10,\"h\":true},{\"i\":\"rock_medium\",\"x\":400,\"y\":300,\"a\":6,\"h\":true},{\"i\":\"rock_small\",\"x\":600,\"y\":200,\"a\":8,\"h\":true},{\"i\":\"fence\",\"x\":50,\"y\":50,\"a\":10,\"h\":true},{\"i\":\"fence\",\"x\":250,\"y\":150,\"a\":12,\"h\":true},{\"i\":\"fence\",\"x\":550,\"y\":350,\"a\":12,\"h\":true},{\"i\":\"rock_large\",\"x\":400,\"y\":70,\"a\":12,\"h\":true},{\"i\":\"rock_large\",\"x\":200,\"y\":200,\"a\":6,\"h\":false},{\"i\":\"tree\",\"x\":5,\"y\":5,\"a\":45,\"h\":true},{\"i\":\"tree\",\"x\":5,\"y\":5,\"a\":20,\"h\":false},{\"i\":\"tree\",\"x\":22,\"y\":22,\"a\":44,\"h\":true},{\"i\":\"tree\",\"x\":22,\"y\":22,\"a\":20,\"h\":false},{\"i\":\"tree\",\"x\":5,\"y\":347,\"a\":45,\"h\":true},{\"i\":\"tree\",\"x\":5,\"y\":364,\"a\":45,\"h\":true},{\"i\":\"tree\",\"x\":735,\"y\":37,\"a\":18,\"h\":false},{\"i\":\"tree\",\"x\":752,\"y\":37,\"a\":18,\"h\":false}],\"enemy_data\":[{\"id\":\"cyclops\",\"index\":0,\"start_position\":{\"x\":350,\"y\":210},\"end_position\":{\"x\":390,\"y\":210},\"move_timer\":2,\"speed\":30,\"attack_timer\":0.4,\"strength\":10,\"health\":100},{\"id\":\"ogre\",\"index\":1,\"start_position\":{\"x\":200,\"y\":320},\"end_position\":{\"x\":220,\"y\":320},\"move_timer\":0.5,\"speed\":45,\"attack_timer\":0.6,\"strength\":20,\"health\":200},{\"id\":\"ghost\",\"index\":2,\"start_position\":{\"x\":100,\"y\":80},\"end_position\":{\"x\":180,\"y\":85},\"move_timer\":2.2,\"speed\":55,\"attack_timer\":0.5,\"strength\":30,\"health\":300},{\"id\":\"ogre\",\"index\":3,\"start_position\":{\"x\":400,\"y\":50},\"end_position\":{\"x\":490,\"y\":50},\"move_timer\":1.7,\"speed\":35,\"attack_timer\":1.0,\"strength\":20,\"health\":200}],\"npc_data\":[{\"id\":\"funny\",\"index\":0,\"start_position\":{\"x\":350,\"y\":180},\"end_position\":{\"x\":350,\"y\":180},\"move_timer\":0,\"speed\":0,\"message\":\"Hello there!\"}]}");
  117. if (!separate_world_data("story_world_v8", json_data_str))
  118. {
  119. FURI_LOG_E("Game", "Failed to separate world data");
  120. }
  121. furi_string_free(json_data_str);
  122. level_set_world(level, manager, "story_world_v8");
  123. game_context->icon_offset = 0;
  124. if (!game_context->imu_present)
  125. {
  126. game_context->icon_offset += ((game_context->icon_count / 10) / 15);
  127. }
  128. player_spawn(level, manager);
  129. }
  130. static const LevelBehaviour _story_world = {
  131. .alloc = NULL,
  132. .free = NULL,
  133. .start = story_draw_world,
  134. .stop = NULL,
  135. .context_size = 0,
  136. };
  137. const LevelBehaviour *story_world()
  138. {
  139. return &_story_world;
  140. }