fixed game logic

This commit is contained in:
2025-03-23 21:41:37 +01:00
parent 507bc9cc86
commit 38008e00bc
7 changed files with 90 additions and 59 deletions

View File

@@ -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();
}
}
}
}

View File

@@ -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()) {

View File

@@ -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
*/

View File

@@ -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;

View File

@@ -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();
}