fixed game logic
This commit is contained in:
@@ -55,6 +55,8 @@ void Game::initialize() {
|
||||
void Game::nextFrame(const std::set<Action>& playerActions) {
|
||||
if (this->lost || this->hasWon()) return;
|
||||
|
||||
bool pieceJustLocked = false;
|
||||
|
||||
if (this->started) {
|
||||
bool AREJustEnded = (this->leftARETime == 1);
|
||||
if (this->leftARETime > 0) {
|
||||
@@ -84,13 +86,14 @@ void Game::nextFrame(const std::set<Action>& playerActions) {
|
||||
|
||||
if (this->lost) {
|
||||
if (initialRotation == NONE) {
|
||||
this->lost = (!this->board.rotate(initialRotation));
|
||||
this->board.rotate(NONE);
|
||||
this->lost = this->board.activePieceInWall();
|
||||
if (this->lost) {
|
||||
this->framesPassed++;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this->lost) {
|
||||
this->framesPassed++;
|
||||
return;
|
||||
}
|
||||
|
||||
/* HOLD */
|
||||
if (playerActions.contains(HOLD) && (!this->heldActions.contains(HOLD))) {
|
||||
@@ -158,6 +161,7 @@ void Game::nextFrame(const std::set<Action>& playerActions) {
|
||||
this->score += HARD_DROP_SCORE;
|
||||
}
|
||||
this->lockPiece();
|
||||
pieceJustLocked = true;
|
||||
}
|
||||
// no need to apply gravity and lock delay if the piece was hard dropped
|
||||
else {
|
||||
@@ -187,6 +191,7 @@ void Game::nextFrame(const std::set<Action>& playerActions) {
|
||||
|
||||
if ((this->totalLockDelay > this->parameters.getLockDelay()) || (this->totalForcedLockDelay > this->parameters.getForcedLockDelay())) {
|
||||
this->lockPiece();
|
||||
pieceJustLocked = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -201,11 +206,11 @@ void Game::nextFrame(const std::set<Action>& playerActions) {
|
||||
}
|
||||
}
|
||||
|
||||
this->heldActions = playerActions;
|
||||
|
||||
if ((!this->started) || this->leftARETime > 0) {
|
||||
for (Action action : playerActions) {
|
||||
this->initialActions.insert(action);
|
||||
if ((!pieceJustLocked) && (!heldActions.contains(action))) {
|
||||
this->initialActions.insert(action);
|
||||
}
|
||||
}
|
||||
|
||||
if (this->heldDAS >= 0) {
|
||||
@@ -219,6 +224,8 @@ void Game::nextFrame(const std::set<Action>& playerActions) {
|
||||
else this->heldDAS = 0;
|
||||
}
|
||||
}
|
||||
|
||||
this->heldActions = playerActions;
|
||||
}
|
||||
|
||||
void Game::resetPiece(bool newPiece) {
|
||||
@@ -302,6 +309,11 @@ void Game::lockPiece() {
|
||||
if (this->leftARETime == 0) {
|
||||
this->lost = this->board.spawnNextPiece();
|
||||
this->resetPiece(true);
|
||||
|
||||
if (this->lost) {
|
||||
this->board.rotate(NONE);
|
||||
this->lost = this->board.activePieceInWall();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,9 +36,12 @@ void GameBoard::initialize() {
|
||||
this->activePiece = nullptr;
|
||||
this->heldPiece = nullptr;
|
||||
this->isLastMoveKick = false;
|
||||
this->movedLeftLast = false;
|
||||
}
|
||||
|
||||
bool GameBoard::moveLeft() {
|
||||
this->movedLeftLast = true;
|
||||
|
||||
if (this->activePieceInWall(Position{-1, 0})) {
|
||||
return false;
|
||||
}
|
||||
@@ -50,6 +53,8 @@ bool GameBoard::moveLeft() {
|
||||
}
|
||||
|
||||
bool GameBoard::moveRight() {
|
||||
this->movedLeftLast = false;
|
||||
|
||||
if (this->activePieceInWall(Position{1, 0})) {
|
||||
return false;
|
||||
}
|
||||
@@ -137,30 +142,21 @@ bool GameBoard::tryKicking(bool testingBottom, const std::set<Position>& safePos
|
||||
bool overlapsRight = true;
|
||||
int i = (j == 0) ? 1 : 0;
|
||||
do {
|
||||
// check right before left arbitrarly, we don't decide this with rotations since it would still be arbitrary with 180° rotations
|
||||
if (overlapsRight) {
|
||||
Position shift{+i, j};
|
||||
if (!this->activePieceOverlaps(safePositions, shift)) {
|
||||
overlapsLeft = false;
|
||||
// we first check the side to which the player moved last
|
||||
if (movedLeftLast) {
|
||||
if (overlapsLeft) {
|
||||
if (this->tryFittingKickedPiece(safePositions, Position({-i, j}), overlapsLeft)) return true;
|
||||
}
|
||||
else {
|
||||
if (!this->activePieceInWall(shift)) {
|
||||
this->activePiecePosition += shift;
|
||||
return true;
|
||||
}
|
||||
if (overlapsRight) {
|
||||
if (this->tryFittingKickedPiece(safePositions, Position({+i, j}), overlapsRight)) return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (overlapsLeft) {
|
||||
Position shift{-i, j};
|
||||
if (!this->activePieceOverlaps(safePositions, shift)) {
|
||||
overlapsLeft = false;
|
||||
else {
|
||||
if (overlapsRight) {
|
||||
if (this->tryFittingKickedPiece(safePositions, Position({+i, j}), overlapsRight)) return true;
|
||||
}
|
||||
else {
|
||||
if (!this->activePieceInWall(shift)) {
|
||||
this->activePiecePosition += shift;
|
||||
return true;
|
||||
}
|
||||
if (overlapsLeft) {
|
||||
if (this->tryFittingKickedPiece(safePositions, Position({-i, j}), overlapsLeft)) return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,6 +173,26 @@ bool GameBoard::tryKicking(bool testingBottom, const std::set<Position>& safePos
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GameBoard::tryFittingKickedPiece(const std::set<Position>& safePositions, const Position& shift, bool& overlaps) {
|
||||
if (!this->activePieceOverlaps(safePositions, shift)) {
|
||||
overlaps = false;
|
||||
}
|
||||
else {
|
||||
if (!this->activePieceInWall(shift)) {
|
||||
this->activePiecePosition += shift;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GameBoard::activePieceOverlaps(const std::set<Position>& safePositions, const Position& shift) const {
|
||||
for (Position position : this->activePiece->getPositions()) {
|
||||
if (safePositions.contains(position + this->activePiecePosition + shift)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GameBoard::hold(Rotation initialRotation) {
|
||||
std::swap(this->activePiece, this->heldPiece);
|
||||
|
||||
@@ -236,6 +252,13 @@ bool GameBoard::spawnNextPiece() {
|
||||
return this->activePieceInWall();
|
||||
}
|
||||
|
||||
bool GameBoard::activePieceInWall(const Position& shift) const {
|
||||
for (Position position : this->activePiece->getPositions()) {
|
||||
if (this->board.getBlock(position + this->activePiecePosition + shift) != NOTHING) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GameBoard::touchesGround() const {
|
||||
return this->activePieceInWall(Position{0, -1});
|
||||
}
|
||||
@@ -257,6 +280,8 @@ LineClear GameBoard::lockPiece() {
|
||||
this->board.changeBlock(position + this->activePiecePosition, this->activePiece->getBlockType());
|
||||
}
|
||||
|
||||
this->activePiece = nullptr;
|
||||
|
||||
return LineClear{this->board.clearRows(), isLockedInPlace, (!isLockedInPlace) && this->isLastMoveKick};
|
||||
}
|
||||
|
||||
@@ -291,20 +316,6 @@ const std::vector<Piece>& GameBoard::getNextPieces() const {
|
||||
return this->nextQueue;
|
||||
}
|
||||
|
||||
bool GameBoard::activePieceInWall(const Position& shift) const {
|
||||
for (Position position : this->activePiece->getPositions()) {
|
||||
if (this->board.getBlock(position + this->activePiecePosition + shift) != NOTHING) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GameBoard::activePieceOverlaps(const std::set<Position>& safePositions, const Position& shift) const {
|
||||
for (Position position : this->activePiece->getPositions()) {
|
||||
if (safePositions.contains(position + this->activePiecePosition + shift)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void GameBoard::goToSpawnPosition() {
|
||||
int lowestPosition = this->activePiece->getLength() - 1;
|
||||
for (Position position : this->activePiece->getPositions()) {
|
||||
|
||||
@@ -22,6 +22,7 @@ class GameBoard {
|
||||
int nextQueueLength; // the number of next pieces seeable at a time
|
||||
std::vector<Piece> nextQueue; // the list of the next pieces to spawn in the board
|
||||
bool isLastMoveKick; // wheter the last action the piece did was kicking
|
||||
bool movedLeftLast; // wheter the last sideway movement was a left one
|
||||
|
||||
public:
|
||||
/**
|
||||
@@ -72,6 +73,18 @@ class GameBoard {
|
||||
*/
|
||||
bool tryKicking(bool testingBottom, const std::set<Position>& safePositions);
|
||||
|
||||
/**
|
||||
* Tries fitting the kicked active piece at the specified position
|
||||
* @return If it suceeded
|
||||
*/
|
||||
bool tryFittingKickedPiece(const std::set<Position>& safePositions, const Position& shift, bool& overlaps);
|
||||
|
||||
/**
|
||||
* Check if one of the active piece's positions shifted by a specified position would overlap with a set of positions
|
||||
* @return If the shifted active piece overlaps with one of the position
|
||||
*/
|
||||
bool activePieceOverlaps(const std::set<Position>& safePositions, const Position& shift = Position{0, 0}) const;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Tries holding the active piece or swapping it if one was already stocked, while trying to apply an initial rotation to the newly spawned piece
|
||||
@@ -85,6 +98,12 @@ class GameBoard {
|
||||
*/
|
||||
bool spawnNextPiece();
|
||||
|
||||
/**
|
||||
* Checks if one of the active piece's positions touches a wall in the board
|
||||
* @return If the active piece is in a wall
|
||||
*/
|
||||
bool activePieceInWall(const Position& shift = Position{0, 0}) const;
|
||||
|
||||
/**
|
||||
* Checks is the active piece as a wall directly below one of its position
|
||||
* @return If it touches a ground
|
||||
@@ -134,18 +153,6 @@ class GameBoard {
|
||||
const std::vector<Piece>& getNextPieces() const;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Checks if one of the active piece's positions touches a wall in the board
|
||||
* @return If the active piece spawned in a wall
|
||||
*/
|
||||
bool activePieceInWall(const Position& shift = Position{0, 0}) const;
|
||||
|
||||
/**
|
||||
* Check if one of the active piece's positions shifted by a specified position would overlap with a set of positions
|
||||
* @return If the shifted active piece overlaps with one of the position
|
||||
*/
|
||||
bool activePieceOverlaps(const std::set<Position>& safePositions, const Position& shift = Position{0, 0}) const;
|
||||
|
||||
/**
|
||||
* Sets the active piece to its spawn position
|
||||
*/
|
||||
|
||||
@@ -38,7 +38,7 @@ void GameParameters::clearLines(int lineNumber) {
|
||||
|
||||
// level increments every 10 lines, stats only changes on level up
|
||||
if (previousLines / 10 < this->clearedLines / 10) {
|
||||
this->level = this->clearedLines / 10;
|
||||
this->level += (this->clearedLines / 10 - previousLines / 10);
|
||||
this->updateStats();
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -74,7 +74,7 @@ void GameSettingsAppMenu::drawFrame() const {
|
||||
this->placeText(text, "ULTRA", 50.f, 25.f, 2, 1);
|
||||
this->placeText(text, "MASTER", 5.f, 35.f, 0, 2);
|
||||
this->placeText(text, "TODO", 25.f, 35.f, 1, 2);
|
||||
this->placeText(text, "TOOD", 50.f, 35.f, 2, 2);
|
||||
this->placeText(text, "TODO", 50.f, 35.f, 2, 2);
|
||||
|
||||
this->renderWindow->display();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user