aboutsummaryrefslogtreecommitdiff
path: root/src/games/tetris/Board.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/games/tetris/Board.cpp')
-rw-r--r--src/games/tetris/Board.cpp139
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);
+ }
+ }
+ }
+}
+