276 lines
12 KiB
C++
276 lines
12 KiB
C++
#include "GamePlayingAppMenu.h"
|
|
|
|
#include "AppMenu.h"
|
|
|
|
#include <stack>
|
|
#include <memory>
|
|
#include <algorithm>
|
|
#include <cmath>
|
|
#include <string>
|
|
#include <SFML/Graphics.hpp>
|
|
|
|
|
|
GamePlayingAppMenu::GamePlayingAppMenu(std::shared_ptr<MenuStack> menuStack, std::shared_ptr<Settings> settings, std::shared_ptr<sf::RenderWindow> 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<Action> 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::Vector2f cellSize(this->cellSizeZoom, this->cellSizeZoom);
|
|
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});
|
|
|
|
sf::RectangleShape cell(cellSize);
|
|
cell.setFillColor(this->getColorOfBlock(block, (block == NOTHING) ? 0 : -30));
|
|
cell.setPosition(this->getBoardBlockPosition(x, y));
|
|
this->renderWindow->draw(cell);
|
|
}
|
|
}
|
|
|
|
if (drawActivePiece) {
|
|
// ghost piece
|
|
sf::Color ghostColor = 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
|
|
float pieceOutlineSize = std::roundf(this->cellSizeZoom / 4);
|
|
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(pieceOutlineSize);
|
|
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 = 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 color = 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).getPositions().contains(Position{x, y})) {
|
|
cell.setFillColor(color);
|
|
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 = 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()->getPositions().contains(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));
|
|
}
|