238 lines
3.9 KiB
C++
238 lines
3.9 KiB
C++
/*
|
|
* 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;
|
|
}
|