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}))
#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);
-}
-
-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();
+ screen_stack->update(((float)duration.count()) / 1000000);
}
-void Game::update_impl(float dt) { TEMP_cached_dt = dt; }
+void Game::draw() { screen_stack->draw(); }
// standard library includes
#include <chrono>
+// local includes
+#include "screen.h"
+
class Game {
public:
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
--- /dev/null
+#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() {}
--- /dev/null
+#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
--- /dev/null
+#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;
+}
--- /dev/null
+#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
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++