aboutsummaryrefslogtreecommitdiff
path: root/src/games/tetris
diff options
context:
space:
mode:
Diffstat (limited to 'src/games/tetris')
-rw-r--r--src/games/tetris/Board.cpp52
-rw-r--r--src/games/tetris/Board.hpp9
-rw-r--r--src/games/tetris/Tetris.cpp259
-rw-r--r--src/games/tetris/Tetris.hpp45
-rw-r--r--src/games/tetris/Tetromino.cpp100
-rw-r--r--src/games/tetris/Tetromino.hpp20
6 files changed, 250 insertions, 235 deletions
diff --git a/src/games/tetris/Board.cpp b/src/games/tetris/Board.cpp
index 1e57b2f..c1af5e1 100644
--- a/src/games/tetris/Board.cpp
+++ b/src/games/tetris/Board.cpp
@@ -1,23 +1,27 @@
-#include <games/tetris/Tetromino.hpp>
#include <games/tetris/Board.hpp>
+#include <games/tetris/Tetromino.hpp>
#include <renderer/Renderer.hpp>
-Board::Board() {
+void
+Board::Reset()
+{
for (int y = 0; y < 2; y++) {
- m_Bitmap[y] = 0xffff; // 1111111111111111
+ m_bitmap[y] = 0xffff; // 1111111111111111
}
for (int y = 2; y < 24; y++) {
- m_Bitmap[y] = 0xe007; // 1110000000000111
+ m_bitmap[y] = 0xe007; // 1110000000000111
}
for (int y = 0; y < 22; y++) {
for (int x = 0; x < 10; x++) {
- m_Idmap[y][x] = Tetromino::tetromino_id_none;
+ m_idmap[y][x] = Tetromino::id_none;
}
}
}
-int32_t Board::PlaceTetromino(Tetromino &tetromino) {
+int32_t
+Board::PlaceTetromino(Tetromino &tetromino)
+{
BoardPos pos = tetromino.GetPos();
Tetromino::TetrominoId id = tetromino.GetId();
uint16_t tetromino_bitmap[4];
@@ -25,10 +29,10 @@ int32_t Board::PlaceTetromino(Tetromino &tetromino) {
// place in Board's Bitmap
- m_Bitmap[pos.y+0] |= tetromino_bitmap[0];
- m_Bitmap[pos.y+1] |= tetromino_bitmap[1];
- m_Bitmap[pos.y+2] |= tetromino_bitmap[2];
- m_Bitmap[pos.y+3] |= tetromino_bitmap[3];
+ m_bitmap[pos.y+0] |= tetromino_bitmap[0];
+ m_bitmap[pos.y+1] |= tetromino_bitmap[1];
+ m_bitmap[pos.y+2] |= tetromino_bitmap[2];
+ m_bitmap[pos.y+3] |= tetromino_bitmap[3];
// place in Board's Idmap
@@ -38,7 +42,7 @@ int32_t Board::PlaceTetromino(Tetromino &tetromino) {
if (tetromino_bitmap[y] & bitmap_x) {
int32_t idmap_x = pos.x + x - 3;
int32_t idmap_y = pos.y + y - 2;
- m_Idmap[idmap_y][idmap_x] = id;
+ m_idmap[idmap_y][idmap_x] = id;
}
}
}
@@ -47,7 +51,9 @@ int32_t Board::PlaceTetromino(Tetromino &tetromino) {
return rows_cleared;
}
-int32_t Board::ClearRows(int32_t y0) {
+int32_t
+Board::ClearRows(int32_t y0)
+{
int32_t rows_cleared = 0;
int32_t y1 = y0 + 3;
@@ -57,28 +63,30 @@ int32_t Board::ClearRows(int32_t y0) {
}
for (int32_t y = y0; y <= y1; y++) {
- if (m_Bitmap[y] == 0xffff) {
+ if (m_bitmap[y] == 0xffff) {
rows_cleared++;
}
else {
- m_Bitmap[y-rows_cleared] = m_Bitmap[y];
- std::copy(m_Idmap[y-2], m_Idmap[y-2] + 10, m_Idmap[y-2-rows_cleared]);
+ m_bitmap[y-rows_cleared] = m_bitmap[y];
+ std::copy(m_idmap[y-2], m_idmap[y-2] + 10, m_idmap[y-2-rows_cleared]);
}
}
for (int32_t y = y1+1; y < 24; y++) {
- m_Bitmap[y-rows_cleared] = m_Bitmap[y];
- std::copy(m_Idmap[y-2], m_Idmap[y-2] + 10, m_Idmap[y-2-rows_cleared]);
+ m_bitmap[y-rows_cleared] = m_bitmap[y];
+ std::copy(m_idmap[y-2], m_idmap[y-2] + 10, m_idmap[y-2-rows_cleared]);
}
for (int32_t y = 24-rows_cleared; y < 24; y++) {
- m_Bitmap[y] = 0xe007;
- std::fill(m_Idmap[y-2], m_Idmap[y-2] + 10, Tetromino::tetromino_id_none);
+ m_bitmap[y] = 0xe007;
+ std::fill(m_idmap[y-2], m_idmap[y-2] + 10, Tetromino::id_none);
}
return rows_cleared;
}
-void Board::Draw(int32_t level) {
+void
+Board::Draw(int32_t level)
+{
float world_width = 4.0f;
float world_height = 3.0f;
float tetromino_size_with_border = world_height / 20.0f;
@@ -113,8 +121,8 @@ void Board::Draw(int32_t level) {
// tetromino parts
for (size_t y = 0; y < 20; y++) {
for (size_t x = 0; x < 10; x++) {
- Tetromino::TetrominoId tetromino_id = (Tetromino::TetrominoId)m_Idmap[y][x];
- if (tetromino_id < Tetromino::tetromino_id_count) {
+ Tetromino::TetrominoId tetromino_id = (Tetromino::TetrominoId)m_idmap[y][x];
+ if (tetromino_id < Tetromino::id_count) {
V2F32 local_pos = {
(float)x * tetromino_size_with_border + tetromino_offset,
(float)y * tetromino_size_with_border + tetromino_offset
diff --git a/src/games/tetris/Board.hpp b/src/games/tetris/Board.hpp
index 2e2edb2..a91556b 100644
--- a/src/games/tetris/Board.hpp
+++ b/src/games/tetris/Board.hpp
@@ -13,8 +13,7 @@ struct BoardPos {
class Board {
public:
- Board();
-
+ void Reset();
int32_t PlaceTetromino(Tetromino &tetromino);
void Draw(int32_t level);
@@ -24,8 +23,8 @@ private:
private:
- friend class Tetromino;
- uint16_t m_Bitmap[24];
- uint8_t m_Idmap[22][10];
+ friend class Tetris;
+ uint16_t m_bitmap[24];
+ uint8_t m_idmap[22][10];
};
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();
}
diff --git a/src/games/tetris/Tetris.hpp b/src/games/tetris/Tetris.hpp
index e517f1c..b3ace1d 100644
--- a/src/games/tetris/Tetris.hpp
+++ b/src/games/tetris/Tetris.hpp
@@ -6,27 +6,18 @@
#include <games/tetris/Board.hpp>
-enum class TetrisRunningState {
- Resume,
- Pause,
- GameOver,
- Restart,
- Exit
-};
-
-
class Tetris : public Game {
public:
- Tetris();
+ Tetris() = default;
bool Update(std::vector<SDL_Event> &events) override;
void HandleTetrominoPlacement();
private:
- void Restart();
+ void Start();
void UpdateResumeState(SDL_Event &event);
void UpdatePauseState(SDL_Event &event);
- uint32_t GetHarddropCount(float dt);
+ uint32_t GetSoftdropCount(float dt);
void HandleGameOver();
void Draw();
@@ -36,7 +27,6 @@ private:
void DrawNextTetromino();
void DrawLevel();
- void DrawPauseMenu();
void DrawGameOverMenu();
private:
@@ -45,23 +35,18 @@ private:
private:
- TetrisRunningState m_RunningState = TetrisRunningState::Resume;
-
- float m_DtInSecondsRemaining = 0.0f;
- uint64_t m_MillisecondsSinceT0Last = SDL_GetTicks();
-
- Board m_Board;
- Tetromino m_ActiveTetromino;
- Tetromino m_NextTetromino;
-
- int32_t m_TetrominoCounters[Tetromino::tetromino_id_count] {};
- int32_t m_Score = 0;
- int32_t m_LineCounter = 0;
- int32_t m_StartingLevel = 0;
- int32_t m_Level = 0;
- int32_t m_SoftdropCounter = 0;
-
- int32_t m_HighScore = 0;
+ Board m_board;
+ Tetromino m_active_tetromino;
+ Tetromino m_next_tetromino;
+
+ int32_t m_tetromino_counters[Tetromino::id_count] {};
+ int32_t m_score = 0;
+ int32_t m_line_counter = 0;
+ int32_t m_starting_level = 0;
+ int32_t m_level = 0;
+ int32_t m_softdrop_counter = 0;
+
+ int32_t m_highscore = 0;
};
diff --git a/src/games/tetris/Tetromino.cpp b/src/games/tetris/Tetromino.cpp
index 9179d6d..97c8808 100644
--- a/src/games/tetris/Tetromino.cpp
+++ b/src/games/tetris/Tetromino.cpp
@@ -59,85 +59,101 @@ static const uint16_t s_left_aligned_bitmaps[7][4][4] = {
};
-Tetromino::TetrominoId Tetromino::GetRandomId() {
- static std::uniform_int_distribution<int> s_Dist(0, tetromino_id_count-1);
+Tetromino::TetrominoId Tetromino::GetRandomId()
+{
+ static std::uniform_int_distribution<int> s_Dist(0, id_count-1);
static std::mt19937 s_Rng((std::random_device()()));
TetrominoId id = static_cast<TetrominoId>(s_Dist(s_Rng));
return id;
}
-Tetromino::Tetromino(uint16_t *board_bitmap) :
- m_Id(GetRandomId()),
- m_Pos{6, 20},
- m_Ori{0},
- m_BoardBitmap(board_bitmap)
-{
-}
-Tetromino::Tetromino(Board &board) :
- Tetromino(board.m_Bitmap)
+void
+Tetromino::Reinit(uint16_t* board_bitmap)
{
+ m_id = GetRandomId();
+ m_pos = {6, 20};
+ m_ori = {0};
+ m_board_bitmap = board_bitmap;
}
-Tetromino::TetrominoId Tetromino::GetId() {
- return m_Id;
+Tetromino::TetrominoId
+Tetromino::GetId()
+{
+ return m_id;
}
-BoardPos Tetromino::GetPos() {
- return m_Pos;
+BoardPos
+Tetromino::GetPos()
+{
+ return m_pos;
}
-void Tetromino::GetBitmap(uint16_t *bitmap) {
- GetBitmap(m_Id, m_Pos, m_Ori, bitmap);
+void
+Tetromino::GetBitmap(uint16_t* bitmap)
+{
+ GetBitmap(m_id, m_pos, m_ori, bitmap);
}
-bool Tetromino::IsCollisionWithBoard() {
- bool is_collision = IsCollisionWithBoard(m_Id, m_Pos, m_Ori, m_BoardBitmap);
+bool
+Tetromino::IsCollisionWithBoard()
+{
+ bool is_collision = IsCollisionWithBoard(m_id, m_pos, m_ori, m_board_bitmap);
return is_collision;
}
-void Tetromino::MaybeRotate(TetrominoRotation rotation) {
- int32_t ori = (m_Ori + rotation) % 4;
- if (!IsCollisionWithBoard(m_Id, m_Pos, ori, m_BoardBitmap)) {
- m_Ori = ori;
+void
+Tetromino::MaybeRotate(TetrominoRotation rotation)
+{
+ int32_t ori = (m_ori + rotation) % 4;
+ if (!IsCollisionWithBoard(m_id, m_pos, ori, m_board_bitmap)) {
+ m_ori = ori;
}
}
-void Tetromino::MaybeMoveHorizontally(TetrominoDirection direction) {
- BoardPos pos = m_Pos;
+void
+Tetromino::MaybeMoveHorizontally(TetrominoDirection direction)
+{
+ BoardPos pos = m_pos;
pos.x += static_cast<int32_t>(direction);
- if (!IsCollisionWithBoard(m_Id, pos, m_Ori, m_BoardBitmap)) {
- m_Pos.x = pos.x;
+ if (!IsCollisionWithBoard(m_id, pos, m_ori, m_board_bitmap)) {
+ m_pos.x = pos.x;
}
}
-bool Tetromino::MaybeMoveDown() {
- BoardPos pos = m_Pos;
+bool
+Tetromino::MaybeMoveDown()
+{
+ BoardPos pos = m_pos;
pos.y -= 1;
- if (!IsCollisionWithBoard(m_Id, pos, m_Ori, m_BoardBitmap)) {
- m_Pos.y = pos.y;
+ if (!IsCollisionWithBoard(m_id, pos, m_ori, m_board_bitmap)) {
+ m_pos.y = pos.y;
return true;
}
return false;
}
-void Tetromino::Draw() const {
+void
+Tetromino::Draw()
+{
float world_width = 4.0f;
float world_height = 3.0f;
float tetromino_size_with_border = world_height / 20.0f;
- float x0 = static_cast<float>(m_Pos.x - 3);
- float y0 = static_cast<float>(m_Pos.y - 2);
+ float x0 = static_cast<float>(m_pos.x - 3);
+ float y0 = static_cast<float>(m_pos.y - 2);
V2F32 world_pos = {
((world_width - tetromino_size_with_border*10) / 2.0f) + x0 * tetromino_size_with_border,
y0 * tetromino_size_with_border
};
- Tetromino::Draw(m_Id, m_Ori, world_pos, 1.0f);
+ Tetromino::Draw(m_id, m_ori, world_pos, 1.0f);
}
-bool Tetromino::IsCollisionWithBoard(TetrominoId id, BoardPos pos, int32_t ori, uint16_t *board_bitmap) {
+bool
+Tetromino::IsCollisionWithBoard(TetrominoId id, BoardPos pos, int32_t ori, uint16_t *board_bitmap)
+{
uint16_t tetromino_bitmap[16];
GetBitmap(id, pos, ori, tetromino_bitmap);
@@ -147,14 +163,18 @@ bool Tetromino::IsCollisionWithBoard(TetrominoId id, BoardPos pos, int32_t ori,
return is_collision;
}
-void Tetromino::GetBitmap(TetrominoId id, BoardPos pos, int32_t ori, uint16_t *bitmap) {
+void
+Tetromino::GetBitmap(TetrominoId id, BoardPos pos, int32_t ori, uint16_t *bitmap)
+{
size_t id_ = static_cast<size_t>(id);
uint64_t *src = (uint64_t*)s_left_aligned_bitmaps[id_][ori];
uint64_t *dest = (uint64_t*)bitmap;
*dest = *src >> pos.x;
}
-Color Tetromino::GetColor(TetrominoId id) {
+Color
+Tetromino::GetColor(TetrominoId id)
+{
using enum TetrominoId;
Color color;
@@ -179,7 +199,9 @@ Color Tetromino::GetColor(TetrominoId id) {
return color;
}
-void Tetromino::Draw(TetrominoId id, int32_t ori, V2F32 pos, float scale) {
+void
+Tetromino::Draw(TetrominoId id, int32_t ori, V2F32 pos, float scale)
+{
int32_t id_ = static_cast<int32_t>(id);
float world_height = 3.0f;
diff --git a/src/games/tetris/Tetromino.hpp b/src/games/tetris/Tetromino.hpp
index 88f71f5..b40555b 100644
--- a/src/games/tetris/Tetromino.hpp
+++ b/src/games/tetris/Tetromino.hpp
@@ -15,8 +15,8 @@ public:
l_piece,
j_piece,
i_piece,
- tetromino_id_count,
- tetromino_id_none,
+ id_count,
+ id_none,
};
enum TetrominoRotation {
@@ -31,21 +31,19 @@ public:
public:
- Tetromino() = delete;
- Tetromino(Board &board);
- Tetromino(uint16_t *board_bitmap);
+ void Reinit(uint16_t* board_bitmap);
TetrominoId GetId();
BoardPos GetPos();
int32_t GetOri();
void GetBitmap(uint16_t *bitmap);
- bool IsCollisionWithBoard(); // for last tetromino to check game over
+ bool IsCollisionWithBoard();
bool MaybeMoveDown();
void MaybeMoveHorizontally(TetrominoDirection direction);
void MaybeRotate(TetrominoRotation rotation);
- void Draw() const;
+ void Draw();
public:
@@ -60,9 +58,9 @@ private:
private:
- TetrominoId m_Id;
- BoardPos m_Pos;
- int32_t m_Ori;
- uint16_t *m_BoardBitmap;
+ TetrominoId m_id;
+ BoardPos m_pos;
+ int32_t m_ori;
+ uint16_t *m_board_bitmap;
};