Create "Screen" abstraction, "test" in TestScreen

This commit is contained in:
Stephen Seo 2023-07-31 16:27:01 +09:00
parent ae52220020
commit a617ef3fb6
8 changed files with 185 additions and 26 deletions

View file

@ -11,10 +11,14 @@ OBJDIR = objdir
SOURCES = \
src/main.cc \
src/game.cc
src/game.cc \
src/screen.cc \
src/screen_test.cc
HEADERS = \
src/game.h
src/game.h \
src/screen.h \
src/screen_test.h
OBJECTS = $(addprefix ${OBJDIR}/,$(subst .cc,.cc.o,${SOURCES}))

View file

@ -1,31 +1,20 @@
#include "game.h"
// standard library includes
#include <string>
// third party includes
#include <raylib.h>
// local includes
#include "screen_test.h"
Game::Game()
: prev_time(std::chrono::steady_clock::now()), TEMP_cached_dt(0.0F) {}
: screen_stack(ScreenStack::new_instance()),
prev_time(std::chrono::steady_clock::now()) {
screen_stack->push_screen<TestScreen>();
}
void Game::update() {
auto next_time = std::chrono::steady_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(
next_time - prev_time);
prev_time = next_time;
update_impl(((float)duration.count()) / 1000000);
screen_stack->update(((float)duration.count()) / 1000000);
}
void Game::draw() {
std::string dt_string =
std::string("Delta-time: ") + std::to_string(TEMP_cached_dt);
BeginDrawing();
ClearBackground(BLACK);
DrawText("Testing...", 100, 100, 30, RAYWHITE);
DrawText(dt_string.c_str(), 100, 140, 30, RAYWHITE);
EndDrawing();
}
void Game::update_impl(float dt) { TEMP_cached_dt = dt; }
void Game::draw() { screen_stack->draw(); }

View file

@ -4,6 +4,9 @@
// standard library includes
#include <chrono>
// local includes
#include "screen.h"
class Game {
public:
Game();
@ -20,10 +23,8 @@ class Game {
void draw();
private:
void update_impl(float dt);
ScreenStack::Ptr screen_stack;
std::chrono::steady_clock::time_point prev_time;
float TEMP_cached_dt;
};
#endif

34
src/screen.cc Normal file
View file

@ -0,0 +1,34 @@
#include "screen.h"
Screen::Screen(std::weak_ptr<ScreenStack> stack) : stack(stack) {}
ScreenStack::Ptr ScreenStack::new_instance() {
std::shared_ptr<ScreenStack> ptr =
std::shared_ptr<ScreenStack>(new ScreenStack{});
ptr->self_weak = ptr;
return ptr;
}
void ScreenStack::update(float dt) {
auto idx = stack.size();
while (idx > 0 && stack.at(--idx)->update(dt)) {
}
}
void ScreenStack::draw() {
auto idx = stack.size();
while (idx > 0 && stack.at(--idx)->draw()) {
}
}
void ScreenStack::push_screen(Screen::Ptr &&screen) {
stack.emplace_back(std::forward<Screen::Ptr>(screen));
}
void ScreenStack::pop_screen() {
if (!stack.empty()) {
stack.pop_back();
}
}
ScreenStack::ScreenStack() : self_weak(), stack() {}

81
src/screen.h Normal file
View file

@ -0,0 +1,81 @@
#ifndef JUMPARTIFACT_DOT_COM_DEMO_0_SCREEN_H_
#define JUMPARTIFACT_DOT_COM_DEMO_0_SCREEN_H_
#include <memory>
#include <vector>
// Forward declaration.
class ScreenStack;
class Screen {
public:
using Ptr = std::unique_ptr<Screen>;
template <typename SubScreen>
static Ptr new_screen(std::weak_ptr<ScreenStack> stack);
virtual ~Screen() {}
// No copy.
Screen(const Screen&) = delete;
Screen& operator=(const Screen&) = delete;
// Allow move.
Screen(Screen&&) = default;
Screen& operator=(Screen&&) = default;
/// Return true if next screen should be updated.
virtual bool update(float dt) = 0;
/// Return true if next screen should be drawn.
virtual bool draw() = 0;
protected:
Screen(std::weak_ptr<ScreenStack> stack);
private:
std::weak_ptr<ScreenStack> stack;
};
class ScreenStack {
public:
using Ptr = std::shared_ptr<ScreenStack>;
using Weak = std::weak_ptr<ScreenStack>;
static Ptr new_instance();
// No copy.
ScreenStack(const ScreenStack&) = delete;
ScreenStack& operator=(const ScreenStack&) = delete;
// Allow move.
ScreenStack(ScreenStack&&) = default;
ScreenStack& operator=(ScreenStack&&) = default;
void update(float dt);
void draw();
void push_screen(Screen::Ptr&& screen);
template <typename SubScreen>
void push_screen();
void pop_screen();
private:
ScreenStack();
Weak self_weak;
std::vector<Screen::Ptr> stack;
};
template <typename SubScreen>
Screen::Ptr Screen::new_screen(std::weak_ptr<ScreenStack> stack) {
return std::unique_ptr<SubScreen>(new SubScreen{stack});
}
template <typename SubScreen>
void ScreenStack::push_screen() {
stack.emplace_back(Screen::new_screen<SubScreen>(self_weak));
}
#endif

28
src/screen_test.cc Normal file
View file

@ -0,0 +1,28 @@
#include "screen_test.h"
// standard library includes
#include <string>
// third party includes
#include <raylib.h>
TestScreen::TestScreen(ScreenStack::Weak weak_ptr)
: Screen(weak_ptr), TEMP_cached_dt(0.0F) {}
TestScreen::~TestScreen() {}
bool TestScreen::update(float dt) {
TEMP_cached_dt = dt;
return false;
}
bool TestScreen::draw() {
std::string dt_string =
std::string("Delta-time: ") + std::to_string(TEMP_cached_dt);
BeginDrawing();
ClearBackground(BLACK);
DrawText("Testing...", 100, 100, 30, RAYWHITE);
DrawText(dt_string.c_str(), 100, 140, 30, RAYWHITE);
EndDrawing();
return false;
}

18
src/screen_test.h Normal file
View file

@ -0,0 +1,18 @@
#ifndef JUMPARTIFACT_DOT_COM_DEMO_O_TEST_SCREEN_H_
#define JUMPARTIFACT_DOT_COM_DEMO_O_TEST_SCREEN_H_
#include "screen.h"
class TestScreen : public Screen {
public:
TestScreen(ScreenStack::Weak weak_ptr);
~TestScreen() override;
bool update(float dt) override;
bool draw() override;
private:
float TEMP_cached_dt;
};
#endif

View file

@ -7,11 +7,15 @@ endif
SOURCES = \
../src/main.cc \
../src/ems.cc \
../src/game.cc
../src/game.cc \
../src/screen.cc \
../src/screen_test.cc
HEADERS = \
../src/ems.h \
../src/game.h
../src/game.h \
../src/screen.h \
../src/screen_test.h
CXX = source ${HOME}/git/emsdk/emsdk_env.sh && em++