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})
# 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)
message(FATAL_ERROR "SDL2_gfx not found")
endif ()
@ -34,7 +34,8 @@ add_executable(Pong src/main.cpp
src/VisibleObjects/Side.h
src/VisibleObjects/Score.h
src/TextScreen.h
src/defaultfont.h)
src/defaultfont.h
src/StartScreen.h)
# Now link the libraries to the target
target_link_libraries(Pong ${SDL2_LIBRARIES} ${SDL2_GFX_LIBRARY} ${SDL2_TTF_LIBRARY})

View File

@ -10,6 +10,7 @@
#include "VisibleObjects/PlayerPaddle.h"
#include "VisibleObjects/Score.h"
#include "TextScreen.h"
#include "StartScreen.h"
enum class GameState {
START_SCREEN, GAME, END_SCREEN
@ -20,7 +21,8 @@ private:
Ball *ball;
Score *score;
PlayerPaddle *leftPaddle, *rightPaddle;
TextScreen *startScreen, *endScreen;
StartScreen *startScreen;
TextScreen *endScreen;
protected:
GameState gameState;
@ -37,7 +39,7 @@ public:
};
score = new Score(5, &this->screenSize, func);
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);
gameState = GameState::START_SCREEN;
}
@ -76,6 +78,8 @@ public:
switch (gameState) {
case GameState::START_SCREEN:
startScreen->update();
if (startScreen->isDone())
gameState = GameState::GAME;
break;
case GameState::GAME:
ball->update();
@ -97,8 +101,9 @@ public:
switch (gameState) {
case GameState::START_SCREEN:
if (event.type == SDL_KEYDOWN)
gameState = GameState::GAME;
if (event.type == SDL_KEYDOWN && !startScreen->hasStartedCounting())
startScreen->startCountDown();
return true;
case GameState::GAME:
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:
std::vector<std::string> lines;
TTF_Font *font;
bool hasUpdated;
SDL_Point *screenSize;
// Regular
std::vector<SDL_Rect> positions;
@ -29,13 +29,16 @@ private:
std::vector<SDL_Surface *> shadowSurfaces;
const int shadowOffset = 3;
protected:
bool hasUpdated;
public:
/**
*
* @param text This class takes care of freeing text
* @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) {
std::cerr << "Font path is not set for this platform (null)" << std::endl;
exit(-1);
@ -46,7 +49,17 @@ public:
exit(-1);
}
initPositions(text);
}
private:
void initPositions(const std::string &text) {
lines = splitString(text, '\n');
surfaces.clear();
shadowSurfaces.clear();
positions.clear();
shadowPositions.clear();
surfaces.reserve(lines.size());
shadowSurfaces.reserve(lines.size());
positions.reserve(lines.size());
@ -67,9 +80,9 @@ public:
positions.push_back(regularPosition);
shadowPositions.push_back(shadowPosition);
}
}
public:
~TextScreen() {
if (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) {
// Draw shadow
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');
initPositions(replaceText);
}
void replaceCharAtIndex(char c, int line, int index) {
@ -118,7 +132,7 @@ public:
lines[line][index] = c;
}
void update() {
virtual void update() {
if (hasUpdated)
return;