From 16fd13d2efda7ac8b76f8abcd23a83102c7c4e47 Mon Sep 17 00:00:00 2001 From: Love Billenius Date: Mon, 29 Jan 2024 19:06:02 +0100 Subject: [PATCH] Let user select max score at start --- CMakeLists.txt | 2 ++ src/Game.cpp | 9 +++-- src/Game.h | 4 ++- src/text/Score.cpp | 4 +-- src/text/Score.h | 6 +++- src/text/ScrollOptionScreen.cpp | 61 +++++++++++++++++++++++++++++++ src/text/ScrollOptionScreen.h | 24 +++++++++++++ src/text/TextScreen.cpp | 64 ++++++++++++++++++++++----------- src/text/TextScreen.h | 16 +++++++-- 9 files changed, 159 insertions(+), 31 deletions(-) create mode 100644 src/text/ScrollOptionScreen.cpp create mode 100644 src/text/ScrollOptionScreen.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 304b0a4..1b3cc9a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,6 +46,8 @@ add_executable(Pong src/main.cpp src/text/OptionScreen.cpp src/text/Score.h src/text/Score.cpp + src/text/ScrollOptionScreen.cpp + src/text/ScrollOptionScreen.h ) # Now link the libraries to the target diff --git a/src/Game.cpp b/src/Game.cpp index fbbed5f..44ac002 100644 --- a/src/Game.cpp +++ b/src/Game.cpp @@ -6,8 +6,9 @@ Game::Game(SDL_Point screenSize) : SdlWrapper("Pong", screenSize, 60), score(new Score(&this->screenSize, 5)), ball(new Ball(&this->screenSize, leftPaddle, rightPaddle, score)), startScreen( - new OptionScreen("Welcome to Pong!\nPress any key to get started...", - &this->screenSize, 4)), endScreen(nullptr), + new ScrollOptionScreen( + "Welcome to Pong!\nUse arrowkeys to adjust max score.\nFinish with enter.", + &this->screenSize, 4, score->maxScore())), endScreen(nullptr), gameState(GameState::START_SCREEN) { } @@ -86,9 +87,7 @@ bool Game::handleEvents() { switch (gameState) { case GameState::START_SCREEN: - if (event.type == SDL_KEYDOWN && !startScreen->hasStartedCounting()) - startScreen->startCountDown(); - + startScreen->handleEvent(event); break; case GameState::GAME: handleGameEvent(event); diff --git a/src/Game.h b/src/Game.h index a6ecc31..241507f 100644 --- a/src/Game.h +++ b/src/Game.h @@ -12,6 +12,7 @@ #include "text/TextScreen.h" #include "text/OptionScreen.h" #include "text/Score.h" +#include "text/ScrollOptionScreen.h" enum class GameState { START_SCREEN, GAME, END_SCREEN @@ -21,7 +22,8 @@ class Game : public SdlWrapper { private: Score *score; PlayerPaddle *leftPaddle, *rightPaddle; - OptionScreen *startScreen, *endScreen; + OptionScreen *endScreen; + ScrollOptionScreen *startScreen; Ball *ball; protected: diff --git a/src/text/Score.cpp b/src/text/Score.cpp index b0f8f3e..ecb5cea 100644 --- a/src/text/Score.cpp +++ b/src/text/Score.cpp @@ -1,6 +1,6 @@ #include "Score.h" -Score::Score(SDL_Point *screenSize, uint8_t max_score) : MAX_SCORE(max_score), leftScore(0), rightScore(0), +Score::Score(SDL_Point *screenSize, uint8_t max_score) : maxScore_(max_score), leftScore(0), rightScore(0), TextScreen("", screenSize, std::make_optional( SDL_Point{screenSize->x / 2 - 50, 10})) { } @@ -34,6 +34,6 @@ void Score::incrementScore(const Side side) { break; } - if (incrementedScore >= MAX_SCORE) + if (incrementedScore >= maxScore_) sideWon_ = side; } \ No newline at end of file diff --git a/src/text/Score.h b/src/text/Score.h index 2f46d21..2ce2872 100644 --- a/src/text/Score.h +++ b/src/text/Score.h @@ -18,7 +18,7 @@ class Score : public TextScreen { private: - const uint8_t MAX_SCORE; + uint8_t maxScore_; std::optional sideWon_; public: @@ -36,5 +36,9 @@ public: void resetScore(); void incrementScore(const Side side); + + uint8_t &maxScore() { + return maxScore_; + } }; diff --git a/src/text/ScrollOptionScreen.cpp b/src/text/ScrollOptionScreen.cpp new file mode 100644 index 0000000..1b644db --- /dev/null +++ b/src/text/ScrollOptionScreen.cpp @@ -0,0 +1,61 @@ +// +// Created by Love on 2024-01-29. +// + +#include "ScrollOptionScreen.h" + +std::string textAppendHelper(std::string string, const std::string &toAppend) { + string.append("\nMax Score: "); + string.append(toAppend); + return std::move(string); +} + +ScrollOptionScreen::ScrollOptionScreen(const std::string &text, SDL_Point *screenSize, int seconds, uint8_t &counterRef) + : OptionScreen(textAppendHelper(text, std::to_string(counterRef)), screenSize, seconds), + counter(counterRef) { +} + + +void ScrollOptionScreen::handleEvent(SDL_Event &event) { + if (event.type == SDL_KEYDOWN) { + switch (event.key.keysym.sym) { + case SDLK_w: + [[fallthrough]]; + case SDLK_UP: + counter++; + shouldUpdate = true; + break; + case SDLK_s: + [[fallthrough]]; + case SDLK_DOWN: + if (counter > 0) { + counter--; + shouldUpdate = true; + } + break; + case SDLK_RETURN: + shouldUpdate = true; + startCountDown(); + break; + } + } +} + +void ScrollOptionScreen::update() { + if (shouldUpdate) { + size_t lineIndex = getAmountOfLines() - 1; + std::string line = getLine(lineIndex); + size_t lastSpace = line.rfind(' '); + if (lastSpace == std::string::npos) { + std::cerr << "Could not find the last space..." << std::endl; + return; + } + line.erase(lastSpace + 1); + line.append(std::to_string(counter)); + + replaceLine(lineIndex, std::move(line)); + shouldUpdate = false; + } + + OptionScreen::update(); +} diff --git a/src/text/ScrollOptionScreen.h b/src/text/ScrollOptionScreen.h new file mode 100644 index 0000000..ba7959f --- /dev/null +++ b/src/text/ScrollOptionScreen.h @@ -0,0 +1,24 @@ +// +// Created by Love on 2024-01-29. +// + +#pragma once + + +#include "OptionScreen.h" + +class ScrollOptionScreen : public OptionScreen { + +private: + uint8_t &counter; + bool shouldUpdate = true; + +public: + ScrollOptionScreen(const std::string &text, SDL_Point *screenSize, int seconds, uint8_t &counterRef); + + void handleEvent(SDL_Event &event); + + void update() override; +}; + + diff --git a/src/text/TextScreen.cpp b/src/text/TextScreen.cpp index 448ea73..5da13ee 100644 --- a/src/text/TextScreen.cpp +++ b/src/text/TextScreen.cpp @@ -1,5 +1,6 @@ #include #include +#include #include "TextScreen.h" #include "optional" @@ -41,34 +42,36 @@ void TextScreen::initPositions(const std::string &text) { surfaces.clear(); shadowSurfaces.clear(); positions.clear(); - shadowPositions.clear(); surfaces.reserve(lines.size()); shadowSurfaces.reserve(lines.size()); positions.reserve(lines.size()); - shadowPositions.reserve(lines.size()); for (int i = 0; i < lines.size(); ++i) { - int textWidth, textHeight; - TTF_SizeText(font, lines[i].c_str(), &textWidth, &textHeight); - - SDL_Point base = basePosition.has_value() ? basePosition.value() : SDL_Point{(screenSize->x - textWidth) / 2, - static_cast((screenSize->y - - textHeight * - (lines.size())) / - 2)}; - - SDL_Rect regularPosition = {base.x, base.y + textHeight * i, textWidth, textHeight}; - SDL_Rect shadowPosition = {base.x + shadowOffset, base.y + textHeight * i + shadowOffset, textWidth, - textHeight}; - positions.push_back(regularPosition); - shadowPositions.push_back(shadowPosition); + auto pair = calculatePositionOf(i); + positions.push_back(pair); } } +Position TextScreen::calculatePositionOf(const int i) const { + int textWidth, textHeight; + TTF_SizeText(font, lines[i].c_str(), &textWidth, &textHeight); + + SDL_Point base = basePosition.has_value() ? basePosition.value() : SDL_Point{(screenSize->x - textWidth) / 2, + static_cast((screenSize->y - + textHeight * + (lines.size())) / + 2)}; + + SDL_Rect regularPosition = {base.x, base.y + textHeight * i, textWidth, textHeight}; + SDL_Rect shadowPosition = {base.x + shadowOffset, base.y + textHeight * i + shadowOffset, textWidth, + textHeight}; + return Position{.shadowPosition=shadowPosition, .regularPosition=regularPosition}; + +} + TextScreen::~TextScreen() { // TTF_CLoseFont & SDL_FreeSurface are null-safe - TTF_CloseFont(font); for (auto *surface: surfaces) SDL_FreeSurface(surface); @@ -81,14 +84,14 @@ void TextScreen::draw(SDL_Renderer *const renderer) { // Draw shadow SDL_Texture *shadowTexture = SDL_CreateTextureFromSurface(renderer, shadowSurfaces[i]); if (shadowTexture != nullptr) { - SDL_RenderCopy(renderer, shadowTexture, nullptr, &shadowPositions[i]); + SDL_RenderCopy(renderer, shadowTexture, nullptr, &positions[i].shadowPosition); SDL_DestroyTexture(shadowTexture); } // Draw text SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, surfaces[i]); if (texture != nullptr) { - SDL_RenderCopy(renderer, texture, nullptr, &positions[i]); + SDL_RenderCopy(renderer, texture, nullptr, &positions[i].regularPosition); SDL_DestroyTexture(texture); } } @@ -126,4 +129,25 @@ void TextScreen::update() { } hasUpdated = true; -} \ No newline at end of file +} + +/** + * + * @param c to replace with + * @param line Should be zero indexed. That means -1 from getAmountOfLines + * @param column Should be zero indexed. That means -1 from getAmountOfColumns + */ +void TextScreen::replaceLine(const size_t index, std::string line) { + lines[index] = std::move(line); + hasUpdated = false; + positions[index] = calculatePositionOf(index); +} + +std::string &TextScreen::getLine(const size_t index) { + return lines[index]; +} + +size_t TextScreen::getAmountOfLines() { + return lines.size(); +} + diff --git a/src/text/TextScreen.h b/src/text/TextScreen.h index 7ef5fa0..041c710 100644 --- a/src/text/TextScreen.h +++ b/src/text/TextScreen.h @@ -12,6 +12,10 @@ #include "../defaultfont.h" #include "iostream" +struct Position { + SDL_Rect shadowPosition; + SDL_Rect regularPosition; +}; class TextScreen { private: @@ -22,11 +26,10 @@ private: std::optional basePosition; // Regular - std::vector positions; + std::vector positions; SDL_Color color = {243, 156, 18, 255}; // Shadow - std::vector shadowPositions; const SDL_Color shadowColor = {243, 156, 18, 100}; const int shadowOffset = 3; @@ -48,8 +51,17 @@ public: void setText(const std::string &replaceText); + void replaceLine(size_t index, std::string line); + + std::string &getLine(size_t index); + + size_t getAmountOfLines(); + virtual void update(); private: void initPositions(const std::string &text); + + Position calculatePositionOf(int i) const; + };