mirror of
				https://github.com/lov3b/Pong.git
				synced 2025-11-04 07:10:16 +01:00 
			
		
		
		
	Let user select max score at start
This commit is contained in:
		@@ -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);
 | 
			
		||||
 
 | 
			
		||||
@@ -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:
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
}
 | 
			
		||||
@@ -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_;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										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 <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();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user