mirror of
https://github.com/lov3b/Pong.git
synced 2025-01-18 04:30:11 +01:00
Let user select max score at start
This commit is contained in:
parent
970fdcb045
commit
16fd13d2ef
@ -46,6 +46,8 @@ add_executable(Pong src/main.cpp
|
|||||||
src/text/OptionScreen.cpp
|
src/text/OptionScreen.cpp
|
||||||
src/text/Score.h
|
src/text/Score.h
|
||||||
src/text/Score.cpp
|
src/text/Score.cpp
|
||||||
|
src/text/ScrollOptionScreen.cpp
|
||||||
|
src/text/ScrollOptionScreen.h
|
||||||
)
|
)
|
||||||
|
|
||||||
# Now link the libraries to the target
|
# Now link the libraries to the target
|
||||||
|
@ -6,8 +6,9 @@ Game::Game(SDL_Point screenSize) : SdlWrapper("Pong", screenSize, 60),
|
|||||||
score(new Score(&this->screenSize, 5)),
|
score(new Score(&this->screenSize, 5)),
|
||||||
ball(new Ball(&this->screenSize, leftPaddle, rightPaddle, score)),
|
ball(new Ball(&this->screenSize, leftPaddle, rightPaddle, score)),
|
||||||
startScreen(
|
startScreen(
|
||||||
new OptionScreen("Welcome to Pong!\nPress any key to get started...",
|
new ScrollOptionScreen(
|
||||||
&this->screenSize, 4)), endScreen(nullptr),
|
"Welcome to Pong!\nUse arrowkeys to adjust max score.\nFinish with enter.",
|
||||||
|
&this->screenSize, 4, score->maxScore())), endScreen(nullptr),
|
||||||
gameState(GameState::START_SCREEN) {
|
gameState(GameState::START_SCREEN) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,9 +87,7 @@ bool Game::handleEvents() {
|
|||||||
|
|
||||||
switch (gameState) {
|
switch (gameState) {
|
||||||
case GameState::START_SCREEN:
|
case GameState::START_SCREEN:
|
||||||
if (event.type == SDL_KEYDOWN && !startScreen->hasStartedCounting())
|
startScreen->handleEvent(event);
|
||||||
startScreen->startCountDown();
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case GameState::GAME:
|
case GameState::GAME:
|
||||||
handleGameEvent(event);
|
handleGameEvent(event);
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include "text/TextScreen.h"
|
#include "text/TextScreen.h"
|
||||||
#include "text/OptionScreen.h"
|
#include "text/OptionScreen.h"
|
||||||
#include "text/Score.h"
|
#include "text/Score.h"
|
||||||
|
#include "text/ScrollOptionScreen.h"
|
||||||
|
|
||||||
enum class GameState {
|
enum class GameState {
|
||||||
START_SCREEN, GAME, END_SCREEN
|
START_SCREEN, GAME, END_SCREEN
|
||||||
@ -21,7 +22,8 @@ class Game : public SdlWrapper {
|
|||||||
private:
|
private:
|
||||||
Score *score;
|
Score *score;
|
||||||
PlayerPaddle *leftPaddle, *rightPaddle;
|
PlayerPaddle *leftPaddle, *rightPaddle;
|
||||||
OptionScreen *startScreen, *endScreen;
|
OptionScreen *endScreen;
|
||||||
|
ScrollOptionScreen *startScreen;
|
||||||
Ball *ball;
|
Ball *ball;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#include "Score.h"
|
#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(
|
TextScreen("", screenSize, std::make_optional(
|
||||||
SDL_Point{screenSize->x / 2 - 50, 10})) {
|
SDL_Point{screenSize->x / 2 - 50, 10})) {
|
||||||
}
|
}
|
||||||
@ -34,6 +34,6 @@ void Score::incrementScore(const Side side) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (incrementedScore >= MAX_SCORE)
|
if (incrementedScore >= maxScore_)
|
||||||
sideWon_ = side;
|
sideWon_ = side;
|
||||||
}
|
}
|
@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
class Score : public TextScreen {
|
class Score : public TextScreen {
|
||||||
private:
|
private:
|
||||||
const uint8_t MAX_SCORE;
|
uint8_t maxScore_;
|
||||||
std::optional<Side> sideWon_;
|
std::optional<Side> sideWon_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -36,5 +36,9 @@ public:
|
|||||||
void resetScore();
|
void resetScore();
|
||||||
|
|
||||||
void incrementScore(const Side side);
|
void incrementScore(const Side side);
|
||||||
|
|
||||||
|
uint8_t &maxScore() {
|
||||||
|
return maxScore_;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
61
src/text/ScrollOptionScreen.cpp
Normal file
61
src/text/ScrollOptionScreen.cpp
Normal 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();
|
||||||
|
}
|
24
src/text/ScrollOptionScreen.h
Normal file
24
src/text/ScrollOptionScreen.h
Normal 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;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <utility>
|
||||||
#include "TextScreen.h"
|
#include "TextScreen.h"
|
||||||
#include "optional"
|
#include "optional"
|
||||||
|
|
||||||
@ -41,34 +42,36 @@ void TextScreen::initPositions(const std::string &text) {
|
|||||||
surfaces.clear();
|
surfaces.clear();
|
||||||
shadowSurfaces.clear();
|
shadowSurfaces.clear();
|
||||||
positions.clear();
|
positions.clear();
|
||||||
shadowPositions.clear();
|
|
||||||
|
|
||||||
surfaces.reserve(lines.size());
|
surfaces.reserve(lines.size());
|
||||||
shadowSurfaces.reserve(lines.size());
|
shadowSurfaces.reserve(lines.size());
|
||||||
positions.reserve(lines.size());
|
positions.reserve(lines.size());
|
||||||
shadowPositions.reserve(lines.size());
|
|
||||||
|
|
||||||
for (int i = 0; i < lines.size(); ++i) {
|
for (int i = 0; i < lines.size(); ++i) {
|
||||||
int textWidth, textHeight;
|
auto pair = calculatePositionOf(i);
|
||||||
TTF_SizeText(font, lines[i].c_str(), &textWidth, &textHeight);
|
positions.push_back(pair);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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() {
|
TextScreen::~TextScreen() {
|
||||||
// TTF_CLoseFont & SDL_FreeSurface are null-safe
|
// TTF_CLoseFont & SDL_FreeSurface are null-safe
|
||||||
|
|
||||||
TTF_CloseFont(font);
|
TTF_CloseFont(font);
|
||||||
for (auto *surface: surfaces)
|
for (auto *surface: surfaces)
|
||||||
SDL_FreeSurface(surface);
|
SDL_FreeSurface(surface);
|
||||||
@ -81,14 +84,14 @@ void TextScreen::draw(SDL_Renderer *const renderer) {
|
|||||||
// Draw shadow
|
// Draw shadow
|
||||||
SDL_Texture *shadowTexture = SDL_CreateTextureFromSurface(renderer, shadowSurfaces[i]);
|
SDL_Texture *shadowTexture = SDL_CreateTextureFromSurface(renderer, shadowSurfaces[i]);
|
||||||
if (shadowTexture != nullptr) {
|
if (shadowTexture != nullptr) {
|
||||||
SDL_RenderCopy(renderer, shadowTexture, nullptr, &shadowPositions[i]);
|
SDL_RenderCopy(renderer, shadowTexture, nullptr, &positions[i].shadowPosition);
|
||||||
SDL_DestroyTexture(shadowTexture);
|
SDL_DestroyTexture(shadowTexture);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw text
|
// Draw text
|
||||||
SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, surfaces[i]);
|
SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, surfaces[i]);
|
||||||
if (texture != nullptr) {
|
if (texture != nullptr) {
|
||||||
SDL_RenderCopy(renderer, texture, nullptr, &positions[i]);
|
SDL_RenderCopy(renderer, texture, nullptr, &positions[i].regularPosition);
|
||||||
SDL_DestroyTexture(texture);
|
SDL_DestroyTexture(texture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -126,4 +129,25 @@ void TextScreen::update() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
hasUpdated = true;
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -12,6 +12,10 @@
|
|||||||
#include "../defaultfont.h"
|
#include "../defaultfont.h"
|
||||||
#include "iostream"
|
#include "iostream"
|
||||||
|
|
||||||
|
struct Position {
|
||||||
|
SDL_Rect shadowPosition;
|
||||||
|
SDL_Rect regularPosition;
|
||||||
|
};
|
||||||
|
|
||||||
class TextScreen {
|
class TextScreen {
|
||||||
private:
|
private:
|
||||||
@ -22,11 +26,10 @@ private:
|
|||||||
std::optional<SDL_Point> basePosition;
|
std::optional<SDL_Point> basePosition;
|
||||||
|
|
||||||
// Regular
|
// Regular
|
||||||
std::vector<SDL_Rect> positions;
|
std::vector<Position> positions;
|
||||||
SDL_Color color = {243, 156, 18, 255};
|
SDL_Color color = {243, 156, 18, 255};
|
||||||
|
|
||||||
// Shadow
|
// Shadow
|
||||||
std::vector<SDL_Rect> shadowPositions;
|
|
||||||
const SDL_Color shadowColor = {243, 156, 18, 100};
|
const SDL_Color shadowColor = {243, 156, 18, 100};
|
||||||
const int shadowOffset = 3;
|
const int shadowOffset = 3;
|
||||||
|
|
||||||
@ -48,8 +51,17 @@ public:
|
|||||||
|
|
||||||
void setText(const std::string &replaceText);
|
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();
|
virtual void update();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void initPositions(const std::string &text);
|
void initPositions(const std::string &text);
|
||||||
|
|
||||||
|
Position calculatePositionOf(int i) const;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user