#include "GamePlayingAppMenu.h" #include "AppMenu.h" #include #include #include #include #include #include GamePlayingAppMenu::GamePlayingAppMenu(std::shared_ptr menuStack, std::shared_ptr settings, std::shared_ptr renderWindow) : AppMenu(menuStack, settings, renderWindow), game(this->settings->getMenu().startGame(this->settings->getGamemode())) { this->startTimer = this->settings->getStartTimerLength() * FRAMES_PER_SECOND; if (this->startTimer == 0) { this->game.start(); } this->paused = false; this->pausePressed = false; this->retryPressed = false; int maxWidthMultiplier = (this->settings->getWindowSizeMultiplier() * 40) / (this->game.getBoard().getWidth()); int maxHeightMultiplier = (this->settings->getWindowSizeMultiplier() * 50) / (this->game.getBoard().getBaseHeight() + 10); this->cellSizeZoom = std::min(maxWidthMultiplier, maxHeightMultiplier); float boardWidth = this->game.getBoard().getWidth() * this->cellSizeZoom; float boardHeight = (this->game.getBoard().getBaseHeight() + 10) * this->cellSizeZoom; this->boardPosition = sf::FloatRect(sf::Vector2f((this->settings->getWindowSizeMultiplier() * 40) - (boardWidth / 2), (this->settings->getWindowSizeMultiplier() * 25) - (boardHeight / 2)), sf::Vector2f(boardWidth, boardHeight)); for (int i = 0; i < 5; i++) { this->nextQueuePosition[i] = sf::FloatRect(sf::Vector2f(this->boardPosition.position.x + boardWidth + (5.f * this->settings->getWindowSizeMultiplier()), (10.f + (10.f * i)) * this->settings->getWindowSizeMultiplier()), sf::Vector2f(8.f * this->settings->getWindowSizeMultiplier(), 8.f * this->settings->getWindowSizeMultiplier())); } this->nextCellSizeZoom = this->nextQueuePosition[0].size.y; for (const auto& piece : this->settings->getMenu().getPiecesList().getSelectedPieces()) { float nextPieceCellSizeZoom = ((int) this->nextQueuePosition[0].size.y) / this->settings->getMenu().getPiecesList().lookAtPiece(piece).getLength(); this->nextCellSizeZoom = std::min(this->nextCellSizeZoom, nextPieceCellSizeZoom); } this->holdBoxPosition = sf::FloatRect(sf::Vector2f(this->boardPosition.position.x - ((8.f + 5.f) * this->settings->getWindowSizeMultiplier()), (10.f) * this->settings->getWindowSizeMultiplier()), sf::Vector2f(8.f * this->settings->getWindowSizeMultiplier(), 8.f * this->settings->getWindowSizeMultiplier())); this->holdCellSizeZoom = this->nextCellSizeZoom; } void GamePlayingAppMenu::computeFrame() { this->updateMetaBinds(); if (this->startTimer > 0) { this->startTimer--; if (this->startTimer == 0) { this->game.start(); } } if (this->escReleased) { this->menuStack->pop(); } else { std::set actions; for (Action action : ACTION_LIST_IN_ORDER) { for (sfKey key : this->settings->getKeybinds().getKeybinds(action)) { if (sf::Keyboard::isKeyPressed(key)) { actions.insert(action); } } } if (actions.contains(RETRY)) { this->retryPressed = true; } else { if (this->retryPressed) { this->game.reset(); this->startTimer = this->settings->getStartTimerLength() * FRAMES_PER_SECOND; if (this->startTimer == 0) { this->game.start(); } } this->retryPressed = false; } if (actions.contains(PAUSE)) { this->pausePressed = true; } else { if (this->pausePressed) { this->paused = (!this->paused); } this->pausePressed = false; } if (!paused) { this->game.nextFrame(actions); } } } void GamePlayingAppMenu::drawFrame() const { this->renderWindow->clear(sf::Color(200, 200, 200)); sf::Color bonesBlockColor(0, 0, 0); sf::Color bonesBlockGhostColor(100, 100, 100); bool areBlockBones = this->game.areBlocksBones(); bool isBoardInvisible = this->game.isBoardInvisible() && !(this->game.hasWon() || this->game.hasLost()); sf::Vector2f cellSize(this->cellSizeZoom, this->cellSizeZoom); float cellOutlineThickness = this->cellSizeZoom / 4; bool drawActivePiece = (this->game.getActivePiece() != nullptr) && (!this->game.hasLost()); // board for (int y = this->game.getBoard().getBaseHeight() + 9; y >= 0; y--) { for (int x = 0; x < this->game.getBoard().getWidth(); x++) { Block block = this->game.getBoard().getBlock(Position(x, y)); if (isBoardInvisible) block = NOTHING; sf::RectangleShape cell(cellSize); cell.setFillColor((areBlockBones && block != NOTHING) ? bonesBlockColor : this->getColorOfBlock(block, (block == NOTHING) ? 0 : -30)); cell.setPosition(this->getBoardBlockPosition(x, y)); this->renderWindow->draw(cell); } } if (drawActivePiece) { // ghost piece sf::Color ghostColor = areBlockBones ? bonesBlockGhostColor : this->getColorOfBlock(this->game.getActivePiece()->getBlockType(), 100); for (const Position& position : this->game.getActivePiece()->getPositions()) { Position cellPosition = (this->game.getGhostPiecePosition() + position); sf::RectangleShape cell(cellSize); cell.setFillColor(ghostColor); cell.setPosition(this->getBoardBlockPosition(cellPosition.x, cellPosition.y)); this->renderWindow->draw(cell); } // active piece outline sf::Color pieceOultlineColor = sf::Color(255, 255 - (255 * this->game.getForcedLockDelayProgression()), 255 - (255 * this->game.getForcedLockDelayProgression())); for (const Position& position : this->game.getActivePiece()->getPositions()) { Position cellPosition = (this->game.getActivePiecePosition() + position); sf::RectangleShape cell(cellSize); cell.setOutlineThickness(cellOutlineThickness); cell.setOutlineColor(pieceOultlineColor); cell.setPosition(this->getBoardBlockPosition(cellPosition.x, cellPosition.y)); this->renderWindow->draw(cell); } } // top out line sf::RectangleShape topOutLine(sf::Vector2f(this->cellSizeZoom * this->game.getBoard().getWidth(), std::roundf(this->cellSizeZoom / 4))); topOutLine.setPosition(this->getBoardBlockPosition(0, this->game.getBoard().getBaseHeight() - 1)); topOutLine.setFillColor(sf::Color(255, 0, 0)); this->renderWindow->draw(topOutLine); if (drawActivePiece) { // active piece sf::Color pieceColor = areBlockBones ? bonesBlockColor : this->getColorOfBlock(this->game.getActivePiece()->getBlockType(), -200 * (this->game.getLockDelayProgression())); for (const Position& position : this->game.getActivePiece()->getPositions()) { Position cellPosition = (this->game.getActivePiecePosition() + position); sf::RectangleShape cell(cellSize); cell.setFillColor(pieceColor); cell.setPosition(this->getBoardBlockPosition(cellPosition.x, cellPosition.y)); this->renderWindow->draw(cell); } } // next queue int upShift = 0; for (int i = 0; i < std::min((int) this->game.getNextPieces().size(), 5); i++) { sf::FloatRect nextBox = this->nextQueuePosition[i]; nextBox.position.y -= upShift; sf::Vector2f nextCellSize(this->nextCellSizeZoom, this->nextCellSizeZoom); sf::Color pieceColor = areBlockBones ? bonesBlockColor : this->getColorOfBlock(this->game.getNextPieces().at(i).getBlockType(), 0); sf::Color boxColor = sf::Color(180, 180, 180); int lowestRank = 0; for (int y = 0; y < this->game.getNextPieces().at(i).getLength(); y++) { for (int x = 0; x < this->game.getNextPieces().at(i).getLength(); x++) { sf::RectangleShape cell(nextCellSize); if (this->game.getNextPieces().at(i).containsSquare(Position(x, y))) { cell.setFillColor(pieceColor); lowestRank = y; } else { cell.setFillColor(boxColor); } cell.setPosition(sf::Vector2f(nextBox.position.x + (x * this->nextCellSizeZoom), nextBox.position.y + ((this->game.getNextPieces().at(i).getLength() - y - 1) * this->nextCellSizeZoom))); this->renderWindow->draw(cell); } } upShift += nextBox.size.y - (this->game.getNextPieces().at(i).getLength() * this->nextCellSizeZoom); } // hold box if (this->game.getHeldPiece() != nullptr) { sf::Vector2f holdCellSize(this->holdCellSizeZoom, this->holdCellSizeZoom); sf::Color color = areBlockBones ? bonesBlockColor : this->getColorOfBlock(this->game.getHeldPiece()->getBlockType(), 0); sf::Color boxColor = sf::Color(180, 180, 180); for (int y = 0; y < this->game.getHeldPiece()->getLength(); y++) { for (int x = 0; x < this->game.getHeldPiece()->getLength(); x++) { sf::RectangleShape cell(holdCellSize); if (this->game.getHeldPiece()->containsSquare(Position(x, y))) { cell.setFillColor(color); } else { cell.setFillColor(boxColor); } cell.setPosition(sf::Vector2f(this->holdBoxPosition.position.x + (x * this->nextCellSizeZoom), this->holdBoxPosition.position.y + ((this->game.getHeldPiece()->getLength() - y - 1) * this->holdCellSizeZoom))); this->renderWindow->draw(cell); } } } // stats int windowSizeMultiplier = this->settings->getWindowSizeMultiplier(); int fontSize = (this->boardPosition.size.x > (windowSizeMultiplier * 30.f)) ? (windowSizeMultiplier) : (windowSizeMultiplier * 2); sf::Text text(this->pressStartFont, "", fontSize); text.setFillColor(sf::Color(0, 0, 0)); int millisecondes = this->game.getFramesPassed() * (1000.f / FRAMES_PER_SECOND); std::string showedMillisecondes = std::to_string(millisecondes % 1000); while (showedMillisecondes.size() < 3) { showedMillisecondes = "0" + showedMillisecondes; } std::string showedSecondes = std::to_string((millisecondes / 1000) % 60); while (showedSecondes.size() < 2) { showedSecondes = "0" + showedSecondes; } std::string showedMinutes = std::to_string((millisecondes / (60 * 1000))); std::string showedTime = showedMinutes + ":" + showedSecondes + "." + showedMillisecondes; this->placeText(text, {}, getGamemodeName(this->settings->getGamemode()), 1.f, 3.f, {}); this->placeText(text, {}, getGamemodeGoal(this->settings->getGamemode()), 1.f, 6.f, {}); if (this->game.isOnB2BChain()) { this->placeText(text, {}, "B2B", 1.f, 22.f, {}); } this->placeText(text, {}, "LINES:" + std::to_string(this->game.getClearedLines()), 1.f, 27.f, {}); this->placeText(text, {}, "LEVEL:" + std::to_string(this->game.getLevel()), 1.f, 32.f, {}); this->placeText(text, {}, "SCORE:" + std::to_string(this->game.getScore()), 1.f, 37.f, {}); this->placeText(text, {}, "GRADE:" + std::to_string(this->game.getGrade()), 1.f, 42.f, {}); this->placeText(text, {}, showedTime, 1.f, 47.f, {}); // game state text.setOutlineColor(sf::Color(255, 255, 255)); text.setOutlineThickness(windowSizeMultiplier / 2.f); text.setCharacterSize(windowSizeMultiplier * 4); if (this->game.hasWon()) { this->placeTitle(text, {}, "WIN", 25.f, {}); } else if (this->game.hasLost()) { this->placeTitle(text, {}, "LOSE", 25.f, {}); } else if (this->paused) { this->placeTitle(text, {}, "PAUSE", 25.f, {}); } else if (this->startTimer > 0) { this->placeTitle(text, {}, std::to_string(((this->startTimer - 1) / ((this->settings->getStartTimerLength() * FRAMES_PER_SECOND) / 4))), 25.f, {}); } this->renderWindow->display(); } sf::Vector2f GamePlayingAppMenu::getBoardBlockPosition(int x, int y) const { return sf::Vector2f(this->boardPosition.position.x + (x * this->cellSizeZoom), this->boardPosition.position.y + ((this->game.getBoard().getBaseHeight() + 9 - y) * this->cellSizeZoom)); }