scene_menu.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. #include "app.h"
  2. #include "game.h"
  3. #include "app_gameplay.h"
  4. #include "racso_sokoban_icons.h"
  5. #include "wave/scene_management.h"
  6. #include "wave/pagination.h"
  7. #include "wave/calc.h"
  8. #include "save_data_manager.h"
  9. #include <furi.h>
  10. #include <gui/gui.h>
  11. #include <storage/storage.h>
  12. const int NONE = -1;
  13. typedef enum MenuState
  14. {
  15. MenuState_Main,
  16. MenuState_CollectionSelection,
  17. MenuState_LevelSelection
  18. } MenuState;
  19. static MenuState menu_state(AppGameplayState* gameplayState)
  20. {
  21. if (gameplayState->selectedCollection == NONE)
  22. return MenuState_Main;
  23. else if (gameplayState->selectedLevel == NONE)
  24. return MenuState_CollectionSelection;
  25. else
  26. return MenuState_LevelSelection;
  27. }
  28. void menu_transition_callback(int from, int to, void* context)
  29. {
  30. AppContext* app = (AppContext*)context;
  31. AppGameplayState* gameplayState = app->gameplay;
  32. if (from == SCENE_MANAGER_NO_SCENE && to == SceneType_Menu)
  33. {
  34. gameplayState->selectedCollection = NONE;
  35. gameplayState->selectedLevel = NONE;
  36. }
  37. }
  38. void menu_render_callback(Canvas* const canvas, void* context)
  39. {
  40. AppContext* app = (AppContext*)context;
  41. AppGameplayState* gameplayState = app->gameplay;
  42. LevelsDatabase* database = app->database;
  43. canvas_clear(canvas);
  44. MenuState menuState = menu_state(gameplayState);
  45. if (menuState == MenuState_Main)
  46. {
  47. canvas_draw_icon(canvas, 0, 0, &I_splash);
  48. canvas_set_color(canvas, ColorBlack);
  49. canvas_set_font(canvas, FontPrimary);
  50. //canvas_draw_str_aligned(canvas, 64, 32, AlignCenter, AlignTop, "SOKOBAN");
  51. for (int x = 0, y = 58, dx = 0; dx <= 3; dx++)
  52. canvas_draw_line(canvas, x + dx, y - dx, x + dx, y + dx);
  53. canvas_draw_icon(canvas, 6, 55, &I_question_mark);
  54. const int START_CENTER_X = 48, START_CENTER_Y = 59;
  55. canvas_draw_circle(canvas, START_CENTER_X, START_CENTER_Y, 4);
  56. canvas_draw_disc(canvas, START_CENTER_X, START_CENTER_Y, 2);
  57. canvas_draw_str_aligned(canvas, START_CENTER_X + 8, START_CENTER_Y + 4, AlignLeft, AlignBottom, "Start");
  58. }
  59. else if (menuState == MenuState_CollectionSelection)
  60. {
  61. canvas_set_color(canvas, ColorBlack);
  62. canvas_set_font(canvas, FontPrimary);
  63. canvas_draw_str_aligned(canvas, 64, 0, AlignCenter, AlignTop, "Collection");
  64. canvas_set_font(canvas, FontKeyboard);
  65. ContinuousPageInfo pageInfo = pagination_continuous_centered(database->collectionsCount, 5, gameplayState->selectedCollection);
  66. for (int i = 0, item = pageInfo.start; i < 5 && item <= pageInfo.end; i++, item++)
  67. {
  68. int y = 12 + i * 10;
  69. char text[64];
  70. if (item == gameplayState->selectedCollection)
  71. snprintf(text, 64, "> %s", database->collections[item].name);
  72. else
  73. snprintf(text, 64, " %s", database->collections[item].name);
  74. canvas_draw_str_aligned(canvas, 0, y, AlignLeft, AlignTop, text);
  75. }
  76. }
  77. else if (menuState == MenuState_LevelSelection)
  78. {
  79. canvas_set_color(canvas, ColorBlack);
  80. canvas_set_font(canvas, FontPrimary);
  81. canvas_draw_str_aligned(canvas, 64, 0, AlignCenter, AlignTop, "Level");
  82. canvas_set_font(canvas, FontKeyboard);
  83. ContinuousPageInfo pageInfo = pagination_continuous_centered(database->collections[gameplayState->selectedCollection].levelsCount, 5, gameplayState->selectedLevel);
  84. for (int i = 0, item = pageInfo.start; i < 5 && item <= pageInfo.end; i++, item++)
  85. {
  86. int y = 12 + i * 10;
  87. int x = 0;
  88. char text[64];
  89. if (item == gameplayState->selectedLevel)
  90. snprintf(text, 64, "> #%d", item + 1);
  91. else
  92. snprintf(text, 64, " #%d", item + 1);
  93. canvas_draw_str_aligned(canvas, x, y, AlignLeft, AlignTop, text);
  94. x += 46;
  95. LevelItem levelItem = database->collections[gameplayState->selectedCollection].levels[item];
  96. const Icon* icon;
  97. if (levelItem.playerBest == 0)
  98. icon = &I_checkbox_empty;
  99. else if (levelItem.playerBest > levelItem.worldBest)
  100. icon = &I_checkbox_checked;
  101. else
  102. icon = &I_star;
  103. canvas_draw_icon(canvas, x, y - 1, icon);
  104. x += 16;
  105. if (levelItem.playerBest == 0)
  106. snprintf(text, 64, " --/%d", levelItem.worldBest);
  107. else
  108. snprintf(text, 64, " %d/%d", levelItem.playerBest, levelItem.worldBest);
  109. canvas_draw_str_aligned(canvas, x, y, AlignLeft, AlignTop, text);
  110. }
  111. }
  112. }
  113. void menu_input_callback(InputKey key, InputType type, void* context)
  114. {
  115. AppContext* app = (AppContext*)context;
  116. AppGameplayState* gameplayState = app->gameplay;
  117. LevelsDatabase* database = app->database;
  118. MenuState state = menu_state(gameplayState);
  119. if (key == InputKeyBack && type == InputTypePress)
  120. {
  121. if (state == MenuState_Main)
  122. scene_manager_set_scene(app->sceneManager, SceneType_None);
  123. else if (state == MenuState_CollectionSelection)
  124. gameplayState->selectedCollection = NONE;
  125. else if (state == MenuState_LevelSelection)
  126. gameplayState->selectedLevel = NONE;
  127. return;
  128. }
  129. if (state == MenuState_Main && key == InputKeyLeft && type == InputTypePress)
  130. {
  131. scene_manager_set_scene(app->sceneManager, SceneType_Credits);
  132. return;
  133. }
  134. if (key == InputKeyOk && type == InputTypePress)
  135. {
  136. if (state == MenuState_Main)
  137. gameplayState->selectedCollection = 0;
  138. else if (state == MenuState_CollectionSelection)
  139. gameplayState->selectedLevel = 0;
  140. else if (state == MenuState_LevelSelection)
  141. {
  142. scene_manager_set_scene(app->sceneManager, SceneType_Game);
  143. return;
  144. }
  145. }
  146. int delta = 0;
  147. if (key == InputKeyUp && (type == InputTypePress || type == InputTypeRepeat))
  148. delta = -1;
  149. else if (key == InputKeyDown && (type == InputTypePress || type == InputTypeRepeat))
  150. delta = 1;
  151. else if (key == InputKeyLeft && (type == InputTypePress || type == InputTypeRepeat))
  152. delta = -5;
  153. else if (key == InputKeyRight && (type == InputTypePress || type == InputTypeRepeat))
  154. delta = 5;
  155. if (state == MenuState_CollectionSelection)
  156. gameplayState->selectedCollection = wrap_single(gameplayState->selectedCollection + delta, 0, database->collectionsCount - 1);
  157. else if (state == MenuState_LevelSelection)
  158. gameplayState->selectedLevel = wrap_single(gameplayState->selectedLevel + delta, 0, database->collections[gameplayState->selectedCollection].levelsCount - 1);
  159. }