level_settings.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. #include "level_settings.h"
  2. /**** Menu ****/
  3. typedef enum {
  4. Sound = 0,
  5. ShowFPS,
  6. Back,
  7. } MenuOption;
  8. typedef struct {
  9. int selected;
  10. } MenuContext;
  11. static void menu_update(Entity* entity, GameManager* manager, void* context) {
  12. UNUSED(entity);
  13. MenuContext* menu_context = context;
  14. GameContext* game_context = game_manager_game_context_get(manager);
  15. InputState input = game_manager_input_get(manager);
  16. if(input.pressed & GameKeyUp || input.pressed & GameKeyDown || input.pressed & GameKeyOk) {
  17. game_sound_play(game_context, &sequence_sound_menu);
  18. }
  19. if(input.pressed & GameKeyBack) {
  20. game_manager_next_level_set(manager, game_context->levels.menu);
  21. }
  22. if(input.pressed & GameKeyUp) {
  23. menu_context->selected--;
  24. if(menu_context->selected < Sound) {
  25. menu_context->selected = Back;
  26. }
  27. }
  28. if(input.pressed & GameKeyDown) {
  29. menu_context->selected++;
  30. if(menu_context->selected > Back) {
  31. menu_context->selected = Sound;
  32. }
  33. }
  34. if(input.pressed & GameKeyOk) {
  35. switch(menu_context->selected) {
  36. case Sound:
  37. game_switch_sound(game_context);
  38. break;
  39. case ShowFPS:
  40. game_switch_show_fps(game_context);
  41. break;
  42. case Back:
  43. game_manager_next_level_set(manager, game_context->levels.menu);
  44. break;
  45. default:
  46. break;
  47. }
  48. }
  49. if(input.pressed & GameKeyRight || input.pressed & GameKeyLeft) {
  50. switch(menu_context->selected) {
  51. case Sound:
  52. game_switch_sound(game_context);
  53. break;
  54. case ShowFPS:
  55. game_switch_show_fps(game_context);
  56. break;
  57. default:
  58. break;
  59. }
  60. }
  61. }
  62. static void menu_render(Entity* entity, GameManager* manager, Canvas* canvas, void* context) {
  63. UNUSED(entity);
  64. MenuContext* menu_context = context;
  65. GameContext* game_context = game_manager_game_context_get(manager);
  66. FuriString* line = furi_string_alloc_set("Sound: ");
  67. if(menu_context->selected == Sound) {
  68. furi_string_set(line, ">Sound: ");
  69. }
  70. if(game_context->settings.sound) {
  71. furi_string_cat(line, "On");
  72. } else {
  73. furi_string_cat(line, "Off");
  74. }
  75. canvas_draw_str_aligned(
  76. canvas, 64 + 3, 18, AlignLeft, AlignCenter, furi_string_get_cstr(line));
  77. furi_string_set(line, "FPS: ");
  78. if(menu_context->selected == ShowFPS) {
  79. furi_string_set(line, ">FPS: ");
  80. }
  81. if(game_context->settings.show_fps) {
  82. furi_string_cat(line, "On");
  83. } else {
  84. furi_string_cat(line, "Off");
  85. }
  86. canvas_draw_str_aligned(
  87. canvas, 64 + 3, 33, AlignLeft, AlignCenter, furi_string_get_cstr(line));
  88. furi_string_set(line, "Back");
  89. if(menu_context->selected == Back) {
  90. furi_string_set(line, ">Back");
  91. }
  92. canvas_draw_str_aligned(
  93. canvas, 64 + 3, 48, AlignLeft, AlignCenter, furi_string_get_cstr(line));
  94. furi_string_free(line);
  95. }
  96. static const EntityDescription menu_desc = {
  97. .start = NULL,
  98. .stop = NULL,
  99. .update = menu_update,
  100. .render = menu_render,
  101. .collision = NULL,
  102. .event = NULL,
  103. .context_size = sizeof(MenuContext),
  104. };
  105. /**** IMU Debug ****/
  106. typedef struct {
  107. float pitch;
  108. float roll;
  109. float yaw;
  110. bool imu_present;
  111. } IMUDebugContext;
  112. static void imu_debug_start(Entity* self, GameManager* manager, void* ctx) {
  113. UNUSED(self);
  114. IMUDebugContext* context = ctx;
  115. context->pitch = 0;
  116. context->roll = 0;
  117. context->yaw = 0;
  118. GameContext* game_context = game_manager_game_context_get(manager);
  119. context->imu_present = game_context->imu_present;
  120. }
  121. static void imu_debug_update(Entity* self, GameManager* manager, void* ctx) {
  122. UNUSED(self);
  123. IMUDebugContext* context = (IMUDebugContext*)ctx;
  124. GameContext* game_context = game_manager_game_context_get(manager);
  125. if(game_context->imu_present) {
  126. context->pitch = imu_pitch_get(game_context->imu);
  127. context->roll = imu_roll_get(game_context->imu);
  128. context->yaw = imu_yaw_get(game_context->imu);
  129. }
  130. }
  131. static void imu_debug_render(Entity* self, GameManager* manager, Canvas* canvas, void* context) {
  132. UNUSED(self);
  133. UNUSED(manager);
  134. Vector pos = {32, 32};
  135. const float radius = 30;
  136. const float max_angle = 45;
  137. const float bubble_radius = 3;
  138. canvas_draw_circle(canvas, pos.x, pos.y, radius);
  139. IMUDebugContext* imu_debug_context = context;
  140. if(imu_debug_context->imu_present) {
  141. const float pitch = -CLAMP(imu_debug_context->pitch, max_angle, -max_angle);
  142. const float roll = -CLAMP(imu_debug_context->roll, max_angle, -max_angle);
  143. const float max_bubble_len = radius - bubble_radius - 2;
  144. Vector ball = {
  145. max_bubble_len * (pitch / max_angle),
  146. max_bubble_len * (roll / max_angle),
  147. };
  148. float bubble_len = sqrtf(ball.x * ball.x + ball.y * ball.y);
  149. if(bubble_len > max_bubble_len) {
  150. ball.x = ball.x * max_bubble_len / bubble_len;
  151. ball.y = ball.y * max_bubble_len / bubble_len;
  152. }
  153. ball = vector_add(pos, ball);
  154. canvas_draw_disc(canvas, ball.x, ball.y, bubble_radius);
  155. } else {
  156. canvas_draw_str_aligned(canvas, pos.x, pos.y + 1, AlignCenter, AlignCenter, "No IMU");
  157. }
  158. }
  159. static const EntityDescription imu_debug_desc = {
  160. .start = imu_debug_start,
  161. .stop = NULL,
  162. .update = imu_debug_update,
  163. .render = imu_debug_render,
  164. .collision = NULL,
  165. .event = NULL,
  166. .context_size = sizeof(IMUDebugContext),
  167. };
  168. /**** Level ****/
  169. static void level_settings_alloc(Level* level, GameManager* manager, void* ctx) {
  170. UNUSED(ctx);
  171. UNUSED(manager);
  172. level_add_entity(level, &imu_debug_desc);
  173. level_add_entity(level, &menu_desc);
  174. }
  175. const LevelBehaviour level_settings = {
  176. .alloc = level_settings_alloc,
  177. .free = NULL,
  178. .start = NULL,
  179. .stop = NULL,
  180. .context_size = 0,
  181. };