diff options
Diffstat (limited to 'src/games/tetris/Tetris.cpp')
| -rw-r--r-- | src/games/tetris/Tetris.cpp | 259 |
1 files changed, 131 insertions, 128 deletions
diff --git a/src/games/tetris/Tetris.cpp b/src/games/tetris/Tetris.cpp index d26649f..3370e78 100644 --- a/src/games/tetris/Tetris.cpp +++ b/src/games/tetris/Tetris.cpp @@ -1,3 +1,4 @@ +#include <games/Game.hpp> #include <games/tetris/Tetromino.hpp> #include <games/tetris/Tetris.hpp> #include <renderer/Renderer.hpp> @@ -8,76 +9,72 @@ #include <fstream> -// Todo: change to new font scaling api in imgui first -// Todo: test text with hardcoded gap + dummy to ensure it gets placed as expected -Tetris::Tetris() : - m_ActiveTetromino(m_Board), - m_NextTetromino(m_Board) +void +Tetris::Start() { - m_TetrominoCounters[(size_t)m_ActiveTetromino.GetId()] += 1; + m_game_status = game_resuming; + + m_tlast_milliseconds = SDL_GetTicks(); + m_dt_remaining_seconds = 0.0f; + + m_board.Reset(); + m_active_tetromino.Reinit(m_board.m_bitmap); + m_next_tetromino.Reinit(m_board.m_bitmap); + m_tetromino_counters[(size_t)m_active_tetromino.GetId()] += 1; + + memset(m_tetromino_counters, 0, sizeof(m_tetromino_counters)); + m_score = 0; + m_line_counter = 0; + m_starting_level = 0; + m_level = 0; + m_softdrop_counter = 0; } -void Tetris::Restart() { - m_RunningState = TetrisRunningState::Resume; - m_DtInSecondsRemaining = 0.0f; - m_MillisecondsSinceT0Last = SDL_GetTicks(); - - // Todo: Don't reconstruct! Make reset methods. - m_Board = Board(); - m_ActiveTetromino = Tetromino(m_Board); - m_NextTetromino = Tetromino(m_Board); - - memset(m_TetrominoCounters, 0, sizeof(m_TetrominoCounters)); - m_Score = 0; - m_LineCounter = 0; - m_StartingLevel = 0; - m_Level = 0; - m_SoftdropCounter = 0; -} - -bool Tetris::Update(std::vector<SDL_Event> &events) { +bool +Tetris::Update(std::vector<SDL_Event> &events) +{ Color clear_color = {0.2f, 0.2f, 0.2f, 1.0f}; g_renderer.SetCameraSize(4.0f, 3.0f); g_renderer.Clear(clear_color); - if (m_RunningState == TetrisRunningState::Restart) { - Restart(); + + if (m_game_status == game_starting) { + Start(); } - uint64_t milliseconds_since_t0 = SDL_GetTicks(); - uint64_t milliseconds_since_t0_last = m_MillisecondsSinceT0Last; - uint64_t milliseconds_dt = milliseconds_since_t0 - milliseconds_since_t0_last; - float seconds_dt = static_cast<float>(milliseconds_dt) / 1000.0f; - m_MillisecondsSinceT0Last = milliseconds_since_t0; + float dt = ProcessDt(); - if (m_RunningState == TetrisRunningState::Resume) { - uint32_t harddrop_count = GetHarddropCount(seconds_dt); - while (harddrop_count) { - bool moved_down = m_ActiveTetromino.MaybeMoveDown(); + + if (m_game_status == game_resuming) { + uint32_t softdrop_count = GetSoftdropCount(dt); // side-effect: m_dt_remaining_seconds + for (uint32_t i{0}; i < softdrop_count; i++) { + bool moved_down = m_active_tetromino.MaybeMoveDown(); if (!moved_down) { HandleTetrominoPlacement(); } - harddrop_count--; } } for (auto &event : events) { - using enum TetrisRunningState; - switch (m_RunningState) { - case Resume: UpdateResumeState(event); break; - case Pause: UpdatePauseState(event); break; + switch (m_game_status) { + case game_resuming: UpdateResumeState(event); break; + case game_paused: UpdatePauseState(event); break; default:; } } - Draw(); + + if (m_game_status == game_exit) { + return false; + } - bool keep_running = m_RunningState != TetrisRunningState::Exit; - return keep_running; + Draw(); + + return true; } void Tetris::UpdateResumeState(SDL_Event &event) { @@ -85,23 +82,23 @@ void Tetris::UpdateResumeState(SDL_Event &event) { case SDL_EVENT_KEY_DOWN: { auto key = event.key.key; if (key == SDLK_RIGHT) { - m_ActiveTetromino.MaybeMoveHorizontally(Tetromino::right); + m_active_tetromino.MaybeMoveHorizontally(Tetromino::right); } else if (key == SDLK_LEFT) { - m_ActiveTetromino.MaybeMoveHorizontally(Tetromino::left); + m_active_tetromino.MaybeMoveHorizontally(Tetromino::left); } else if (key == SDLK_DOWN) { - bool moved_down = m_ActiveTetromino.MaybeMoveDown(); + bool moved_down = m_active_tetromino.MaybeMoveDown(); if (!moved_down) { HandleTetrominoPlacement(); } else { - m_SoftdropCounter++; + m_softdrop_counter++; } } else if (key == SDLK_X) { - m_ActiveTetromino.MaybeRotate(Tetromino::rotate_clockwise); + m_active_tetromino.MaybeRotate(Tetromino::rotate_clockwise); } else if (key == SDLK_Z || key == SDLK_Y) { - m_ActiveTetromino.MaybeRotate(Tetromino::rotate_counter_clockwise); + m_active_tetromino.MaybeRotate(Tetromino::rotate_counter_clockwise); } else if (key == SDLK_ESCAPE) { - m_RunningState = TetrisRunningState::Pause; + m_game_status = game_paused; } } default:; @@ -113,75 +110,81 @@ void Tetris::UpdatePauseState(SDL_Event &event) { case SDL_EVENT_KEY_DOWN: { auto key = event.key.key; if (key == SDLK_ESCAPE) { - m_RunningState = TetrisRunningState::Resume; + m_game_status = game_resuming; } } default:; } } -void Tetris::HandleTetrominoPlacement() { - int32_t rows_cleared = m_Board.PlaceTetromino(m_ActiveTetromino); +void +Tetris::HandleTetrominoPlacement() +{ + int32_t rows_cleared = m_board.PlaceTetromino(m_active_tetromino); - m_ActiveTetromino = m_NextTetromino; - m_NextTetromino = Tetromino{m_Board}; + m_active_tetromino = m_next_tetromino; + m_next_tetromino.Reinit(m_board.m_bitmap); - if (m_ActiveTetromino.IsCollisionWithBoard()) { + if (m_active_tetromino.IsCollisionWithBoard()) { HandleGameOver(); return; } - m_LineCounter += rows_cleared; - m_TetrominoCounters[m_ActiveTetromino.GetId()] += 1; + m_line_counter += rows_cleared; + m_tetromino_counters[m_active_tetromino.GetId()] += 1; if (rows_cleared == 1) { - m_Score += 40 * (m_Level + 1); + m_score += 40 * (m_level + 1); } else if (rows_cleared == 2) { - m_Score += 100 * (m_Level + 1); + m_score += 100 * (m_level + 1); } else if (rows_cleared == 3) { - m_Score += 300 * (m_Level + 1); + m_score += 300 * (m_level + 1); } else if (rows_cleared == 4) { - m_Score += 1200 * (m_Level + 1); + m_score += 1200 * (m_level + 1); } - m_Score += m_SoftdropCounter; - m_SoftdropCounter = 0; + m_score += m_softdrop_counter; + m_softdrop_counter = 0; - m_Level = m_StartingLevel + m_LineCounter / 10; + m_level = m_starting_level + m_line_counter / 10; } -uint32_t Tetris::GetHarddropCount(float dt) { +uint32_t +Tetris::GetSoftdropCount(float dt) +{ float nes_frame_time = 1.0f / 60; int32_t nes_frames_per_cell; - if (m_Level <= 8) nes_frames_per_cell = 48 - m_Level * 5; - else if (m_Level == 9) nes_frames_per_cell = 6; - else if (m_Level <= 12) nes_frames_per_cell = 5; - else if (m_Level <= 15) nes_frames_per_cell = 4; - else if (m_Level <= 18) nes_frames_per_cell = 3; - else if (m_Level <= 28) nes_frames_per_cell = 2; + if (m_level <= 8) nes_frames_per_cell = 48 - m_level * 5; + else if (m_level == 9) nes_frames_per_cell = 6; + else if (m_level <= 12) nes_frames_per_cell = 5; + else if (m_level <= 15) nes_frames_per_cell = 4; + else if (m_level <= 18) nes_frames_per_cell = 3; + else if (m_level <= 28) nes_frames_per_cell = 2; else nes_frames_per_cell = 1; float dt_level = static_cast<float>(nes_frames_per_cell) * nes_frame_time; - float dt_total = m_DtInSecondsRemaining + dt; - uint32_t harddrop_count = 0; - while (dt_total > dt_level) { - harddrop_count += 1; - dt_total -= dt_level; + uint32_t softdrop_count = 0; + while (dt > dt_level) { + softdrop_count += 1; + dt -= dt_level; } - m_DtInSecondsRemaining = dt_total; - return harddrop_count; + + m_dt_remaining_seconds = dt; + return softdrop_count; } -void Tetris::HandleGameOver() { - m_RunningState = TetrisRunningState::GameOver; +void +Tetris::HandleGameOver() +{ + m_game_status = game_over; const char *filepath = "tetris_highscore.txt"; int32_t highscore = 0; @@ -195,16 +198,16 @@ void Tetris::HandleGameOver() { SDL_LogInfo(0, "Tetris: cannot open tetris_highscore.txt for reading"); } - if (highscore > 0 && highscore > m_HighScore) { - m_HighScore = highscore; + if (highscore > 0 && highscore > m_highscore) { + m_highscore = highscore; } - if (m_Score > m_HighScore) { - m_HighScore = m_Score; + if (m_score > m_highscore) { + m_highscore = m_score; std::ofstream highscore_file_out { filepath }; if (highscore_file_out) { - highscore_file_out << m_HighScore << std::endl; + highscore_file_out << m_highscore << std::endl; highscore_file_out.close(); } else { @@ -213,9 +216,11 @@ void Tetris::HandleGameOver() { } } -void Tetris::Draw() { - m_Board.Draw(m_Level); - m_ActiveTetromino.Draw(); +void +Tetris::Draw() +{ + m_board.Draw(m_level); + m_active_tetromino.Draw(); DrawNextTetromino(); DrawStatistics(); @@ -224,52 +229,44 @@ void Tetris::Draw() { DrawScore(); // Todo: Use transparency - if (m_RunningState == TetrisRunningState::Pause) { - DrawPauseMenu(); + if (m_game_status == game_paused) { + DrawGamePausedMenu(); } - else if (m_RunningState == TetrisRunningState::GameOver) { + else if (m_game_status == game_over) { DrawGameOverMenu(); } } -void Tetris::DrawPauseMenu() { - ImGui::Begin("TetrisPause", nullptr, s_MenuImGuiWindowFlags); - if (ImGui::Button("Resume")) { - m_RunningState = TetrisRunningState::Resume; - } - if (ImGui::Button("Restart")) { - m_RunningState = TetrisRunningState::Restart; - } - if (ImGui::Button("Exit")) { - m_RunningState = TetrisRunningState::Exit; - } - ImGui::End(); -} - -void Tetris::DrawGameOverMenu() { +void +Tetris::DrawGameOverMenu() +{ ImGui::Begin("TetrisGameOver", nullptr, s_MenuImGuiWindowFlags); - ImGui::Text("Score = %d", m_Score); - ImGui::Text("HighScore = %d", m_HighScore); + ImGui::Text("Score = %d", m_score); + ImGui::Text("HighScore = %d", m_highscore); if (ImGui::Button("Restart")) { - m_RunningState = TetrisRunningState::Restart; + m_game_status = game_starting; } if (ImGui::Button("Exit")) { - m_RunningState = TetrisRunningState::Exit; + m_game_status = game_exit; } ImGui::End(); } -void Tetris::DrawLineCounter() { +void +Tetris::DrawLineCounter() +{ V2F32 view_pos = {0.5f, 2.6f}; ImVec2 screen_pos = g_renderer.ViewPosToScreenPosImGui(view_pos); ImGui::SetNextWindowPos(screen_pos); ImGui::Begin("TetrisLines", nullptr, s_DefaultImGuiWindowFlags); - ImGui::Text("LINES - %d", m_LineCounter); + ImGui::Text("LINES - %d", m_line_counter); ImGui::End(); } -void Tetris::DrawStatistics() { +void +Tetris::DrawStatistics() +{ V2F32 view_tetrominoes_pos = {0.4f, 1.8f}; V2F32 view_advance = {0.0f, 0.2f}; @@ -313,36 +310,40 @@ void Tetris::DrawStatistics() { ImGui::SetNextWindowPos(screen_text_pos); ImGui::Begin("TetrisStatistics", nullptr, s_DefaultImGuiWindowFlags); - ImGui::Text("%d", m_TetrominoCounters[Tetromino::t_piece]); + ImGui::Text("%d", m_tetromino_counters[Tetromino::t_piece]); ImGui::Dummy(screen_text_gap); - ImGui::Text("%d", m_TetrominoCounters[Tetromino::j_piece]); + ImGui::Text("%d", m_tetromino_counters[Tetromino::j_piece]); ImGui::Dummy(screen_text_gap); - ImGui::Text("%d", m_TetrominoCounters[Tetromino::z_piece]); + ImGui::Text("%d", m_tetromino_counters[Tetromino::z_piece]); ImGui::Dummy(screen_text_gap); - ImGui::Text("%d", m_TetrominoCounters[Tetromino::o_piece]); + ImGui::Text("%d", m_tetromino_counters[Tetromino::o_piece]); ImGui::Dummy(screen_text_gap); - ImGui::Text("%d", m_TetrominoCounters[Tetromino::s_piece]); + ImGui::Text("%d", m_tetromino_counters[Tetromino::s_piece]); ImGui::Dummy(screen_text_gap); - ImGui::Text("%d", m_TetrominoCounters[Tetromino::l_piece]); + ImGui::Text("%d", m_tetromino_counters[Tetromino::l_piece]); ImGui::Dummy(screen_text_gap); - ImGui::Text("%d", m_TetrominoCounters[Tetromino::i_piece]); + ImGui::Text("%d", m_tetromino_counters[Tetromino::i_piece]); ImGui::Dummy(screen_text_gap); ImGui::End(); } -void Tetris::DrawScore() { +void +Tetris::DrawScore() +{ V2F32 view_pos = {3.0f, 2.2f}; ImVec2 screen_pos = g_renderer.ViewPosToScreenPosImGui(view_pos); ImGui::SetNextWindowPos(screen_pos); ImGui::Begin("TetrisScore", nullptr, s_DefaultImGuiWindowFlags); ImGui::Text("Score"); - ImGui::Text("%d", m_Score); + ImGui::Text("%d", m_score); ImGui::End(); } -void Tetris::DrawNextTetromino() { +void +Tetris::DrawNextTetromino() +{ V2F32 text_view_pos = {3.0f, 1.8f}; ImVec2 text_screen_pos = g_renderer.ViewPosToScreenPosImGui(text_view_pos); @@ -353,17 +354,19 @@ void Tetris::DrawNextTetromino() { V2F32 tetromino_view_pos = {3.0, 1.4f}; - Tetromino::Draw(m_NextTetromino.GetId(), 0, tetromino_view_pos, 0.5f); + Tetromino::Draw(m_next_tetromino.GetId(), 0, tetromino_view_pos, 0.5f); } -void Tetris::DrawLevel() { +void +Tetris::DrawLevel() +{ V2F32 view_pos = {3.0f, 1.2f}; ImVec2 screen_pos = g_renderer.ViewPosToScreenPosImGui(view_pos); ImGui::SetNextWindowPos(screen_pos); ImGui::Begin("TetrisLevel", nullptr, s_DefaultImGuiWindowFlags); ImGui::Text("Level"); - ImGui::Text("%d", m_Level); + ImGui::Text("%d", m_level); ImGui::End(); } |
