/* * TetrisGame.cpp * * Created on: May 5, 2013 * Author: chibi_000 */ #include "TetrisGame.h" #include TetrisGame::TetrisGame(int w, int h, const PieceGenerator& pg) : grid(w, h), gen(pg) { this->score = 0; this->level = 1; this->cx = 0; this->cy = 0; this->next = gen.getRandomPieceRotated(); this->pickNextPiece(); } TetrisGame::~TetrisGame() { } int TetrisGame::xToPiece(int x_g) { return x_g - cx; } int TetrisGame::xToGrid(int x_p) { return x_p + cx; } int TetrisGame::yToPiece(int y_g) { return y_g - cy; } int TetrisGame::yToGrid(int y_p) { return y_p + cy; } void TetrisGame::pickNextPiece() { // Next becomes current this->current = this->next; // Pick a new piece this->next = gen.getRandomPieceRotated(); // Set position to middle center this->cy = -this->current.getHeight(); this->cx = ( grid.getWidth() - current.getWidth() ) / 2; } void TetrisGame::putPieceInGrid() { for (int x = 0; x < current.getWidth(); x++) for (int y = 0; y < current.getHeight(); y++) grid.set( xToGrid(x), yToGrid(y), grid.get( xToGrid(x), yToGrid(y) ) + current.get(x, y) ); } int TetrisGame::markFullLines() { int total_rows = 0; // For each row for (int y = 0; y < grid.getHeight(); y++) { // Count non-empty cells int count = 0; for (int x = 0; x < grid.getWidth(); x++) count += ( grid.get(x, y) > 0 ) ? 1 : 0; // Count equal to width = full line if (count == grid.getWidth()) { total_rows++; for (int x = 0; x < grid.getWidth(); x++) grid.set(x, y, -1); } } // Return found rows return total_rows; } void TetrisGame::removeFullLines() { for (int yto = grid.getHeight()-1, yfrom = yto; yto >= 0; yto--, yfrom--) { // Skip full lines while (grid.get(0, yfrom) == -1 && yfrom >= 0) yfrom--; // Remove content for (int x = 0; x < grid.getWidth(); x++) if (yfrom < 0) grid.set(x, yto, 0); else grid.set(x, yto, grid.get(x, yfrom)); } } bool TetrisGame::isGameOver() { for (int x = 0; x < grid.getWidth(); x++) if (grid.get(x, 0) != 0) return true; return false; } bool TetrisGame::collides(int cx, int cy, const Piece& p) { // Check bounds if (cx < 0 || cx + p.getWidth() > grid.getWidth()) return true; if (cy + p.getHeight() > grid.getHeight()) return true; // Check every piece for (int x = 0; x < p.getWidth(); x++) for (int y = 0; y < p.getHeight(); y++) if ( y+cy >= 0 && p.get(x, y) != 0 && grid.get(x+cx, y+cy) != 0 ) return true; return false; } bool TetrisGame::collidesDown() { return this->collides(cx, cy+1, current); } bool TetrisGame::collidesLeft() { return this->collides(cx-1, cy, current); } bool TetrisGame::collidesRight() { return this->collides(cx+1, cy, current); } void TetrisGame::moveLeft() { if (!this->collidesLeft()) this->cx--; } void TetrisGame::moveRight() { if (!this->collidesRight()) this->cx++; } void TetrisGame::moveDown() { while (!this->collidesDown()) this->cy++; } void TetrisGame::rotate() { Piece rot = current.rotate(); if (!this->collides(cx, cy, rot)) current = rot; } void TetrisGame::tick() { // Check if game is over if (this->isGameOver()) return; // Remove full lines this->removeFullLines(); // Piece is down if (this->collidesDown()) { this->putPieceInGrid(); this->pickNextPiece(); int count = this->markFullLines(); // Calculate score this->score += (1<<(count - 1)) * 100; if (this->score > (1<<(level - 1)) * 5000) this->level++; } // Piece is not down, simply move it else this->cy++; } int TetrisGame::get(int x, int y) { bool col = cx <= x && x < cx + current.getWidth(); bool row = cy <= y && y < cy + current.getHeight(); if (col && row) return grid.get(x, y) + current.get( xToPiece(x), yToPiece(y) ); return grid.get(x, y); } Piece TetrisGame::getNextPiece() { return next; } int TetrisGame::getScore() { return score; } int TetrisGame::getLevel() { return level; } int TetrisGame::getTickTime() { float l = sqrtf(this->level); return 800 / l; }