diff options
Diffstat (limited to 'src/games/tetris/Board.cpp')
-rw-r--r-- | src/games/tetris/Board.cpp | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/src/games/tetris/Board.cpp b/src/games/tetris/Board.cpp new file mode 100644 index 0000000..9dff135 --- /dev/null +++ b/src/games/tetris/Board.cpp @@ -0,0 +1,139 @@ +#include <renderer/RenderGroup.hpp> +#include <games/tetris/Tetromino.hpp> +#include <games/tetris/Board.hpp> + +Board::Board() { + for (int y = 0; y < 2; y++) { + m_Bitmap[y] = 0xffff; // 1111111111111111 + } + for (int y = 2; y < 24; y++) { + m_Bitmap[y] = 0xe007; // 1110000000000111 + } + + for (int y = 0; y < 22; y++) { + for (int x = 0; x < 10; x++) { + m_Idmap[y][x] = (uint8_t)TetrominoId::TETROMINO_ID_NONE; + } + } +} + +int32_t Board::PlaceTetromino(Tetromino &tetromino) { + BoardPos pos = tetromino.GetPos(); + TetrominoId id = tetromino.GetId(); + uint16_t tetromino_bitmap[4]; + tetromino.GetBitmap(tetromino_bitmap); + + + // check if Tetromino cannot be placed (Game Over) + if (tetromino.IsCollisionWithBoard()) { + return -1; + } + + + // 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]; + + + // place in Board's Idmap + for (int32_t y = 0; y < 4; y++) { + for (int32_t x = 0; x < 4; x++) { + int32_t bitmap_x = 0x8000 >> (pos.x + x); + 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] = static_cast<uint8_t>(id); + } + } + } + + int32_t rows_cleared = ClearRows(pos.y); + return rows_cleared; +} + +int32_t Board::ClearRows(int32_t y0) { + int32_t rows_cleared = 0; + int32_t y1 = y0 + 3; + + // ignore for y = {0,1}. Those bitmap rows are all 1's for collision testing + if (y0 < 2) { + y0 += 2 - y0; + } + + for (int32_t y = y0; y <= y1; y++) { + 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]); + } + } + 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]); + } + 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, (uint8_t)TetrominoId::TETROMINO_ID_NONE); + } + + + return rows_cleared; +} + +void Board::Draw(int32_t level, RenderGroup& render_group) { + float world_width = 4.0f; + float world_height = 3.0f; + float tetromino_size_with_border = world_height / 20.0f; + float tetromino_size = 0.8f * tetromino_size_with_border; + float tetromino_offset = 0.1f * tetromino_size_with_border; + V2F32 board_world_pos = { + (world_width - tetromino_size_with_border*10) / 2.0f, + 0.0f + }; + + + // background + V3F32 bg_world_pos = { + board_world_pos.x, + board_world_pos.y, + 0.0f + }; + V2F32 bg_world_dim = { + tetromino_size_with_border * 10, + tetromino_size_with_border * 20 + }; + V3F32 bg_color = {0.0f, 0.0f, 0.0f}; + render_group.PushRectangle(bg_world_pos, bg_world_dim, bg_color); + + + // tetromino parts + for (size_t y = 0; y < 20; y++) { + for (size_t x = 0; x < 10; x++) { + uint8_t tetromino_id = m_Idmap[y][x]; + if (tetromino_id < (uint8_t)TetrominoId::TETROMINO_ID_COUNT) { + V2F32 local_pos = { + (float)x * tetromino_size_with_border + tetromino_offset, + (float)y * tetromino_size_with_border + tetromino_offset + }; + V2F32 local_dim = {tetromino_size, tetromino_size}; + + + V3F32 world_pos = { + board_world_pos.x + local_pos.x, + board_world_pos.y + local_pos.y, + 1.0f + }; + V2F32 world_dim = local_dim; + + + V3F32 color = Tetromino::GetColor(static_cast<TetrominoId>(tetromino_id)); + render_group.PushRectangle(world_pos, world_dim, color); + } + } + } +} + |