Let user select max score at start

This commit is contained in:
Love 2024-01-29 19:06:02 +01:00
parent 970fdcb045
commit 16fd13d2ef
9 changed files with 159 additions and 31 deletions

View File

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

View File

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

View File

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

View File

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

View File

@ -18,7 +18,7 @@
class Score : public TextScreen {
private:
const uint8_t MAX_SCORE;
uint8_t maxScore_;
std::optional<Side> sideWon_;
public:
@ -36,5 +36,9 @@ public:
void resetScore();
void incrementScore(const Side side);
uint8_t &maxScore() {
return maxScore_;
}
};

View File

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

View File

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

View File

@ -1,5 +1,6 @@
#include <string>
#include <sstream>
#include <utility>
#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<int>((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<int>((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;
}
}
/**
*
* @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();
}

View File

@ -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<SDL_Point> basePosition;
// Regular
std::vector<SDL_Rect> positions;
std::vector<Position> positions;
SDL_Color color = {243, 156, 18, 255};
// Shadow
std::vector<SDL_Rect> 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;
};