MenuState.cxx 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. #include "MenuState.hxx"
  2. #include "PlayingState.hxx"
  3. #include "GameStateManager.hxx"
  4. #include "TranslationManager.hxx"
  5. #include "../SDLRenderer.hxx"
  6. #include <array>
  7. void MenuState::on_enter(GameStateManager& gsm)
  8. {
  9. active_button_ = 0;
  10. auto const& tm = TranslationManager::instance();
  11. new_game_button_.set_title(tm.get_translation("New game"));
  12. continue_button_.set_title(tm.get_translation("Continue"));
  13. high_score_button_.set_title(tm.get_translation("High Scores"));
  14. credits_button_.set_title(tm.get_translation("Credits"));
  15. quit_button_.set_title(tm.get_translation("Quit"));
  16. game_.reset();
  17. if (auto const parent = gsm.parent(); parent!=nullptr) {
  18. continue_button_.set_visible(true);
  19. if (auto const game = dynamic_cast<PlayingState*>(parent); game!=nullptr) {
  20. game_ = game;
  21. active_button_ = 1;
  22. }
  23. }
  24. else {
  25. continue_button_.set_visible(false);
  26. }
  27. new_game_button_.set_on_click([&gsm] {
  28. if (gsm.parent()!=nullptr)
  29. gsm.pop_state();
  30. gsm.replace_state(GameStates::Game);
  31. });
  32. continue_button_.set_on_click([&gsm] {
  33. gsm.pop_state();
  34. });
  35. high_score_button_.set_on_click([&gsm] {
  36. gsm.push_state(GameStates::HighScores);
  37. });
  38. credits_button_.set_on_click([&gsm] {
  39. gsm.push_state(GameStates::Credits);
  40. });
  41. quit_button_.set_on_click([&gsm] {
  42. while (gsm.current()!=nullptr) {
  43. gsm.pop_state();
  44. }
  45. });
  46. SDL_ShowCursor(SDL_ENABLE);
  47. }
  48. void MenuState::on_event(GameStateManager& gsm, SDL_Event const& evt)
  49. {
  50. if (evt.type==SDL_KEYUP) {
  51. switch (evt.key.keysym.scancode) {
  52. default:
  53. break;
  54. case SDL_SCANCODE_PAUSE:
  55. if (gsm.parent()==nullptr)
  56. break;
  57. [[fallthrough]];
  58. case SDL_SCANCODE_ESCAPE:
  59. gsm.pop_state();
  60. break;
  61. case SDL_SCANCODE_UP:
  62. SDL_ShowCursor(SDL_DISABLE);
  63. --active_button_;
  64. if (active_button_<0)
  65. active_button_ = 4;
  66. else if (active_button_==1 && !continue_button_.is_visible())
  67. active_button_ = 0;
  68. break;
  69. case SDL_SCANCODE_DOWN:
  70. SDL_ShowCursor(SDL_DISABLE);
  71. ++active_button_;
  72. if (active_button_>4)
  73. active_button_ = 0;
  74. else if (active_button_==1 && !continue_button_.is_visible())
  75. active_button_ = 2;
  76. break;
  77. case SDL_SCANCODE_RETURN:
  78. switch (active_button_) {
  79. case 0:
  80. new_game_button_.trigger();
  81. break;
  82. case 1:
  83. continue_button_.trigger();
  84. break;
  85. case 2:
  86. high_score_button_.trigger();
  87. break;
  88. case 3:
  89. credits_button_.trigger();
  90. break;
  91. case 4:
  92. quit_button_.trigger();
  93. break;
  94. }
  95. break;
  96. }
  97. }
  98. else if (evt.type==SDL_MOUSEMOTION) {
  99. SDL_ShowCursor(SDL_ENABLE);
  100. auto const x = evt.motion.x;
  101. auto const y = evt.motion.y;
  102. std::array<Button*, 5> buttons{&new_game_button_, nullptr, &high_score_button_, &credits_button_, &quit_button_};
  103. if (continue_button_.is_visible())
  104. buttons[1] = &continue_button_;
  105. for (std::size_t n = 0; n<buttons.size(); ++n) {
  106. if (buttons[n]==nullptr)
  107. continue;
  108. auto const box = buttons[n]->get_bounding_box();
  109. if (x>=box.x && x<=box.x+box.w && y>=box.y && y<=box.y+box.h) {
  110. active_button_ = static_cast<int>(n);
  111. break;
  112. }
  113. }
  114. }
  115. }
  116. void MenuState::update(GameStateManager& gsm, std::chrono::milliseconds const delta_time)
  117. {
  118. (void) delta_time;
  119. auto adjust_button_size = [this, idx = 0](Button& btn) mutable {
  120. if (idx++==active_button_) {
  121. btn.resize(BUTTON_WIDTH, BUTTON_HEIGHT);
  122. }
  123. else {
  124. btn.resize(BUTTON_WIDTH-ACTIVE_SIZE_DIFF, BUTTON_HEIGHT-ACTIVE_SIZE_DIFF);
  125. }
  126. };
  127. for (auto const btn: {&new_game_button_, &continue_button_, &high_score_button_, &credits_button_, &quit_button_}) {
  128. adjust_button_size(*btn);
  129. btn->update();
  130. }
  131. }
  132. void MenuState::render(SDLRenderer& renderer)
  133. {
  134. int screen_w, screen_h;
  135. SDL_GetRendererOutputSize(renderer, &screen_w, &screen_h);
  136. int const button_count = continue_button_.is_visible() ? 5 : 4;
  137. int const x = (screen_w-BUTTON_WIDTH)/2;
  138. int y = (screen_h-(button_count*BUTTON_HEIGHT+(button_count-1)*20))/2;
  139. auto const adjust_button_position = [](Button& btn, int x, int y) {
  140. auto const box = btn.get_bounding_box();
  141. auto const dw = BUTTON_WIDTH-box.w;
  142. auto const dh = BUTTON_HEIGHT-box.h;
  143. btn.move(x+dw/2, y+dh/2);
  144. };
  145. adjust_button_position(new_game_button_, x, y);
  146. if (continue_button_.is_visible()) {
  147. adjust_button_position(continue_button_, x, y += BUTTON_HEIGHT+20);
  148. }
  149. adjust_button_position(high_score_button_, x, y += BUTTON_HEIGHT+20);
  150. adjust_button_position(credits_button_, x, y += BUTTON_HEIGHT+20);
  151. adjust_button_position(quit_button_, x, y+BUTTON_HEIGHT+20);
  152. SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE);
  153. SDL_RenderClear(renderer);
  154. if (game_.has_value()) {
  155. game_.value()->render_game(renderer, false);
  156. }
  157. SDL_SetRenderDrawColor(renderer, 0, 0, 0, 200);
  158. SDL_RenderFillRect(renderer, nullptr);
  159. new_game_button_.render(renderer);
  160. continue_button_.render(renderer);
  161. high_score_button_.render(renderer);
  162. credits_button_.render(renderer);
  163. quit_button_.render(renderer);
  164. SDL_RenderPresent(renderer);
  165. }
  166. void MenuState::on_leave()
  167. {
  168. SDL_ShowCursor(SDL_DISABLE);
  169. }