level_menu.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. #include "level_menu.h"
  2. #include "../game.h"
  3. typedef struct {
  4. Sprite* sprite;
  5. Vector pos_start;
  6. Vector pos_end;
  7. float duration;
  8. float time;
  9. } MovingSpriteContext;
  10. /***** Moving Sprite *****/
  11. static void moving_sprite_update(Entity* entity, GameManager* manager, void* context) {
  12. UNUSED(manager);
  13. MovingSpriteContext* sprite_context = context;
  14. // lerp position between start and end for duration
  15. if(sprite_context->time < sprite_context->duration) {
  16. Vector dir = vector_sub(sprite_context->pos_end, sprite_context->pos_start);
  17. Vector len = vector_mulf(dir, sprite_context->time / sprite_context->duration);
  18. Vector pos = vector_add(sprite_context->pos_start, len);
  19. entity_pos_set(entity, pos);
  20. sprite_context->time += 1.0f;
  21. } else {
  22. entity_pos_set(entity, sprite_context->pos_end);
  23. }
  24. }
  25. static void
  26. moving_sprite_render(Entity* entity, GameManager* manager, Canvas* canvas, void* context) {
  27. UNUSED(manager);
  28. MovingSpriteContext* sprite_context = context;
  29. if(sprite_context->sprite) {
  30. Vector pos = entity_pos_get(entity);
  31. canvas_draw_sprite(canvas, sprite_context->sprite, pos.x, pos.y);
  32. }
  33. }
  34. static void moving_sprite_init(
  35. Entity* entity,
  36. GameManager* manager,
  37. Vector start,
  38. Vector end,
  39. const char* sprite_name) {
  40. MovingSpriteContext* sprite_context = entity_context_get(entity);
  41. sprite_context->pos_start = start;
  42. sprite_context->pos_end = end;
  43. sprite_context->duration = 30.0f;
  44. sprite_context->time = 0;
  45. sprite_context->sprite = game_manager_sprite_load(manager, sprite_name);
  46. }
  47. static void moving_sprite_reset(Entity* entity) {
  48. MovingSpriteContext* sprite_context = entity_context_get(entity);
  49. sprite_context->time = 0;
  50. }
  51. static const EntityDescription moving_sprite_desc = {
  52. .start = NULL,
  53. .stop = NULL,
  54. .update = moving_sprite_update,
  55. .render = moving_sprite_render,
  56. .collision = NULL,
  57. .event = NULL,
  58. .context_size = sizeof(MovingSpriteContext),
  59. };
  60. /***** Menu *****/
  61. typedef struct {
  62. int selected;
  63. } MenuContext;
  64. static void menu_update(Entity* entity, GameManager* manager, void* context) {
  65. UNUSED(entity);
  66. MenuContext* menu_context = context;
  67. GameContext* game_context = game_manager_game_context_get(manager);
  68. InputState input = game_manager_input_get(manager);
  69. if(input.pressed & GameKeyBack) {
  70. game_manager_game_stop(manager);
  71. }
  72. if(input.pressed & GameKeyUp) {
  73. menu_context->selected--;
  74. if(menu_context->selected < 0) {
  75. menu_context->selected = 2;
  76. }
  77. }
  78. if(input.pressed & GameKeyDown) {
  79. menu_context->selected++;
  80. if(menu_context->selected > 2) {
  81. menu_context->selected = 0;
  82. }
  83. }
  84. if(input.pressed & GameKeyUp || input.pressed & GameKeyDown || input.pressed & GameKeyOk) {
  85. game_sound_play(game_context, &sequence_sound_menu);
  86. }
  87. if(input.pressed & GameKeyOk) {
  88. switch(menu_context->selected) {
  89. case 0:
  90. game_manager_next_level_set(manager, game_context->levels.game);
  91. break;
  92. case 1:
  93. game_manager_next_level_set(manager, game_context->levels.settings);
  94. break;
  95. case 2:
  96. game_manager_game_stop(manager);
  97. break;
  98. default:
  99. break;
  100. }
  101. }
  102. }
  103. #include "../fonts/fonts.h"
  104. static void menu_render(Entity* entity, GameManager* manager, Canvas* canvas, void* context) {
  105. UNUSED(entity);
  106. UNUSED(manager);
  107. MenuContext* menu_context = context;
  108. const char* line_1 = "Play";
  109. const char* line_2 = "Settings";
  110. const char* line_3 = "Exit";
  111. if(menu_context->selected == 0) {
  112. line_1 = ">Play";
  113. } else if(menu_context->selected == 1) {
  114. line_2 = ">Settings";
  115. } else if(menu_context->selected == 2) {
  116. line_3 = ">Exit";
  117. }
  118. canvas_draw_str_aligned(canvas, 64, 39, AlignCenter, AlignCenter, line_1);
  119. canvas_draw_str_aligned(canvas, 64, 49, AlignCenter, AlignCenter, line_2);
  120. canvas_draw_str_aligned(canvas, 64, 59, AlignCenter, AlignCenter, line_3);
  121. }
  122. static const EntityDescription menu_desc = {
  123. .start = NULL,
  124. .stop = NULL,
  125. .update = menu_update,
  126. .render = menu_render,
  127. .collision = NULL,
  128. .event = NULL,
  129. .context_size = sizeof(MenuContext),
  130. };
  131. /***** Level *****/
  132. typedef struct {
  133. Entity* arkanoid;
  134. Entity* air;
  135. } LevelMenuContext;
  136. static void level_menu_alloc(Level* level, GameManager* manager, void* context) {
  137. LevelMenuContext* menu_context = context;
  138. const float start = 256; // 0, due to the canvas draw limitations
  139. menu_context->arkanoid = level_add_entity(level, &moving_sprite_desc);
  140. moving_sprite_init(
  141. menu_context->arkanoid,
  142. manager,
  143. (Vector){.x = start - 50, .y = start + 11},
  144. (Vector){.x = start + 7, .y = start + 11},
  145. "logo_arkanoid.fxbm");
  146. menu_context->air = level_add_entity(level, &moving_sprite_desc);
  147. moving_sprite_init(
  148. menu_context->air,
  149. manager,
  150. (Vector){.x = start + 20, .y = start - 27},
  151. (Vector){.x = start + 20, .y = start + 0},
  152. "logo_air.fxbm");
  153. level_add_entity(level, &menu_desc);
  154. }
  155. static void level_menu_start(Level* level, GameManager* manager, void* context) {
  156. UNUSED(level);
  157. UNUSED(manager);
  158. LevelMenuContext* menu_context = context;
  159. moving_sprite_reset(menu_context->arkanoid);
  160. moving_sprite_reset(menu_context->air);
  161. }
  162. const LevelBehaviour level_menu = {
  163. .alloc = level_menu_alloc,
  164. .free = NULL,
  165. .start = level_menu_start,
  166. .stop = NULL,
  167. .context_size = sizeof(LevelMenuContext),
  168. };