start screen working

This commit is contained in:
Love 2024-01-29 10:26:05 +01:00
parent 5c87e2d918
commit a86a3c170a
4 changed files with 96 additions and 12 deletions

View File

@ -11,7 +11,7 @@ find_package(SDL2 REQUIRED)
include_directories(${SDL2_INCLUDE_DIRS}) include_directories(${SDL2_INCLUDE_DIRS})
# SDL2 Gfx # SDL2 Gfx
find_library(SDL2_GFX_LIBRARY NAMES SDL2_gfx SDL2_gfxd) find_library(SDL2_GFX_LIBRARY NAMES SDL2_gfx SDL2_gfxd libSDL2_gfx)
if (NOT SDL2_GFX_LIBRARY) if (NOT SDL2_GFX_LIBRARY)
message(FATAL_ERROR "SDL2_gfx not found") message(FATAL_ERROR "SDL2_gfx not found")
endif () endif ()
@ -34,7 +34,8 @@ add_executable(Pong src/main.cpp
src/VisibleObjects/Side.h src/VisibleObjects/Side.h
src/VisibleObjects/Score.h src/VisibleObjects/Score.h
src/TextScreen.h src/TextScreen.h
src/defaultfont.h) src/defaultfont.h
src/StartScreen.h)
# Now link the libraries to the target # Now link the libraries to the target
target_link_libraries(Pong ${SDL2_LIBRARIES} ${SDL2_GFX_LIBRARY} ${SDL2_TTF_LIBRARY}) target_link_libraries(Pong ${SDL2_LIBRARIES} ${SDL2_GFX_LIBRARY} ${SDL2_TTF_LIBRARY})

View File

@ -10,6 +10,7 @@
#include "VisibleObjects/PlayerPaddle.h" #include "VisibleObjects/PlayerPaddle.h"
#include "VisibleObjects/Score.h" #include "VisibleObjects/Score.h"
#include "TextScreen.h" #include "TextScreen.h"
#include "StartScreen.h"
enum class GameState { enum class GameState {
START_SCREEN, GAME, END_SCREEN START_SCREEN, GAME, END_SCREEN
@ -20,7 +21,8 @@ private:
Ball *ball; Ball *ball;
Score *score; Score *score;
PlayerPaddle *leftPaddle, *rightPaddle; PlayerPaddle *leftPaddle, *rightPaddle;
TextScreen *startScreen, *endScreen; StartScreen *startScreen;
TextScreen *endScreen;
protected: protected:
GameState gameState; GameState gameState;
@ -37,7 +39,7 @@ public:
}; };
score = new Score(5, &this->screenSize, func); score = new Score(5, &this->screenSize, func);
ball = new Ball(&this->screenSize, leftPaddle, rightPaddle, score); ball = new Ball(&this->screenSize, leftPaddle, rightPaddle, score);
startScreen = new TextScreen("Welcome to Pong!\nPress any key to get started...", &this->screenSize); startScreen = new StartScreen(&this->screenSize, 4);
endScreen = new TextScreen("", &this->screenSize); endScreen = new TextScreen("", &this->screenSize);
gameState = GameState::START_SCREEN; gameState = GameState::START_SCREEN;
} }
@ -76,6 +78,8 @@ public:
switch (gameState) { switch (gameState) {
case GameState::START_SCREEN: case GameState::START_SCREEN:
startScreen->update(); startScreen->update();
if (startScreen->isDone())
gameState = GameState::GAME;
break; break;
case GameState::GAME: case GameState::GAME:
ball->update(); ball->update();
@ -97,8 +101,9 @@ public:
switch (gameState) { switch (gameState) {
case GameState::START_SCREEN: case GameState::START_SCREEN:
if (event.type == SDL_KEYDOWN) if (event.type == SDL_KEYDOWN && !startScreen->hasStartedCounting())
gameState = GameState::GAME; startScreen->startCountDown();
return true; return true;
case GameState::GAME: case GameState::GAME:
handleGameEvent(event); handleGameEvent(event);

64
src/StartScreen.h Normal file
View File

@ -0,0 +1,64 @@
//
// Created by Love on 2024-01-29.
//
#pragma once
#include "TextScreen.h"
#include "chrono"
int_least64_t getCurrentEpochTimeMillis() {
auto now = std::chrono::system_clock::now();
auto now_ms = std::chrono::time_point_cast<std::chrono::milliseconds>(now);
auto epoch = now_ms.time_since_epoch();
auto value = std::chrono::duration_cast<std::chrono::milliseconds>(epoch);
return value.count();
}
class StartScreen : public TextScreen {
private:
bool hasStartedCounting_ = false;
int_least64_t nextMsEpoch = 0;
int stepsToDo, stepsDone = 0;
bool isDone_ = false;
public:
[[nodiscard]] const bool &isDone() const {
return isDone_;
}
[[nodiscard]] const bool &hasStartedCounting() const {
return hasStartedCounting_;
}
public:
StartScreen(SDL_Point *screenSize, int seconds)
: TextScreen("Welcome to Pong!\nPress any key to get started...", screenSize), stepsToDo(seconds) {
}
void update() override {
auto now = getCurrentEpochTimeMillis();
if (hasStartedCounting_ && nextMsEpoch <= now) {
if (stepsDone < stepsToDo) {
std::string s = std::to_string(stepsToDo - stepsDone);
setText(s);
nextMsEpoch = now + 1000;
hasUpdated = false;
stepsDone++;
} else {
isDone_ = true;
}
}
TextScreen::update();
}
void startCountDown() {
auto epochMs = getCurrentEpochTimeMillis();
nextMsEpoch = epochMs + 1000;
hasStartedCounting_ = true;
stepsDone = 0;
}
};

View File

@ -16,7 +16,7 @@ class TextScreen {
private: private:
std::vector<std::string> lines; std::vector<std::string> lines;
TTF_Font *font; TTF_Font *font;
bool hasUpdated; SDL_Point *screenSize;
// Regular // Regular
std::vector<SDL_Rect> positions; std::vector<SDL_Rect> positions;
@ -29,13 +29,16 @@ private:
std::vector<SDL_Surface *> shadowSurfaces; std::vector<SDL_Surface *> shadowSurfaces;
const int shadowOffset = 3; const int shadowOffset = 3;
protected:
bool hasUpdated;
public: public:
/** /**
* *
* @param text This class takes care of freeing text * @param text This class takes care of freeing text
* @param screenSize This won't be freed by this class * @param screenSize This won't be freed by this class
*/ */
TextScreen(const std::string& text, SDL_Point *screenSize) : hasUpdated(false) { TextScreen(const std::string &text, SDL_Point *screenSize) : hasUpdated(false), screenSize(screenSize) {
if (defaultFontPath == nullptr) { if (defaultFontPath == nullptr) {
std::cerr << "Font path is not set for this platform (null)" << std::endl; std::cerr << "Font path is not set for this platform (null)" << std::endl;
exit(-1); exit(-1);
@ -46,7 +49,17 @@ public:
exit(-1); exit(-1);
} }
initPositions(text);
}
private:
void initPositions(const std::string &text) {
lines = splitString(text, '\n'); lines = splitString(text, '\n');
surfaces.clear();
shadowSurfaces.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());
@ -67,9 +80,9 @@ public:
positions.push_back(regularPosition); positions.push_back(regularPosition);
shadowPositions.push_back(shadowPosition); shadowPositions.push_back(shadowPosition);
} }
} }
public:
~TextScreen() { ~TextScreen() {
if (font) if (font)
TTF_CloseFont(font); TTF_CloseFont(font);
@ -80,7 +93,7 @@ public:
} }
void draw(SDL_Renderer *renderer) { virtual void draw(SDL_Renderer *renderer) {
for (int i = 0; i < surfaces.size(); ++i) { for (int i = 0; i < surfaces.size(); ++i) {
// Draw shadow // Draw shadow
SDL_Texture *shadowTexture = SDL_CreateTextureFromSurface(renderer, shadowSurfaces[i]); SDL_Texture *shadowTexture = SDL_CreateTextureFromSurface(renderer, shadowSurfaces[i]);
@ -98,8 +111,9 @@ public:
} }
} }
void setText(std::string &replaceText) { void setText(const std::string &replaceText) {
lines = splitString(replaceText, '\n'); lines = splitString(replaceText, '\n');
initPositions(replaceText);
} }
void replaceCharAtIndex(char c, int line, int index) { void replaceCharAtIndex(char c, int line, int index) {
@ -118,7 +132,7 @@ public:
lines[line][index] = c; lines[line][index] = c;
} }
void update() { virtual void update() {
if (hasUpdated) if (hasUpdated)
return; return;