tetris/Logic/TetrisGame.cpp

238 lines
3.9 KiB
C++
Raw Normal View History

2018-02-05 23:44:42 +00:00
/*
* TetrisGame.cpp
*
* Created on: May 5, 2013
* Author: chibi_000
*/
#include "TetrisGame.h"
#include <math.h>
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;
}