]> git.seodisparate.com - jumpartifact.com_demo_0/commitdiff
Defer ScreenStack actions to start of update
authorStephen Seo <seo.disparate@gmail.com>
Mon, 31 Jul 2023 11:39:46 +0000 (20:39 +0900)
committerStephen Seo <seo.disparate@gmail.com>
Mon, 31 Jul 2023 11:39:46 +0000 (20:39 +0900)
src/game.cc
src/screen.cc
src/screen.h

index 95324d77be249ed4655d76c1bb3708d6308f8900..a1fdab1be6223542e167021bb6adb88768162cd5 100644 (file)
@@ -5,9 +5,7 @@
 
 Game::Game()
     : screen_stack(ScreenStack::new_instance()),
-      prev_time(std::chrono::steady_clock::now()) {
-  screen_stack->push_screen<TestScreen>();
-}
+      prev_time(std::chrono::steady_clock::now()) {}
 
 void Game::update() {
   auto next_time = std::chrono::steady_clock::now();
index bd855cf526e9e2b189ebf9fe6031cb17ace93a78..8cd1bcc4bb006446405956bdf2f29b808e00eade 100644 (file)
@@ -1,7 +1,24 @@
 #include "screen.h"
 
+// standard library includes
+#include <cassert>
+#ifndef NDEBUG
+#include <iostream>
+#endif  // NDEBUG
+
+// local includes
+#include "screen_test.h"
+
 Screen::Screen(std::weak_ptr<ScreenStack> stack) : stack(stack) {}
 
+ScreenStack::PendingAction::PendingAction() : screen(), action(Action::NOP) {}
+
+ScreenStack::PendingAction::PendingAction(Action action)
+    : screen(), action(action) {}
+
+ScreenStack::PendingAction::PendingAction(Screen::Ptr &&screen)
+    : screen(std::forward<Screen::Ptr>(screen)), action(Action::PUSH_SCREEN) {}
+
 ScreenStack::Ptr ScreenStack::new_instance() {
   std::shared_ptr<ScreenStack> ptr =
       std::shared_ptr<ScreenStack>(new ScreenStack{});
@@ -10,7 +27,17 @@ ScreenStack::Ptr ScreenStack::new_instance() {
 }
 
 void ScreenStack::update(float dt) {
+  handle_pending_actions();
+
   auto idx = stack.size();
+  if (idx == 0) {
+#ifndef NDEBUG
+    std::cerr << "WARNING: Stack is empty, pushing TestScreen...\n";
+#endif  // NDEBUG
+    push_screen(Screen::new_screen<TestScreen>(self_weak));
+    update(dt);
+    return;
+  }
   while (idx > 0 && stack.at(--idx)->update(dt)) {
   }
 }
@@ -22,13 +49,33 @@ void ScreenStack::draw() {
 }
 
 void ScreenStack::push_screen(Screen::Ptr &&screen) {
-  stack.emplace_back(std::forward<Screen::Ptr>(screen));
+  actions.push_back(PendingAction(std::forward<Screen::Ptr>(screen)));
 }
 
 void ScreenStack::pop_screen() {
-  if (!stack.empty()) {
-    stack.pop_back();
-  }
+  actions.push_back(PendingAction(Action::POP_SCREEN));
 }
 
-ScreenStack::ScreenStack() : self_weak(), stack() {}
+ScreenStack::ScreenStack() : self_weak(), stack(), actions() {}
+
+void ScreenStack::handle_pending_actions() {
+  while (!actions.empty()) {
+    switch (actions.front().action) {
+      case Action::PUSH_SCREEN:
+        stack.push_back(std::move(actions.front().screen));
+        break;
+      case Action::POP_SCREEN:
+        if (!stack.empty()) {
+          stack.pop_back();
+        }
+        break;
+      case Action::NOP:
+        // Intentionally left blank.
+        break;
+      default:
+        assert(!"unreachable");
+        break;
+    }
+    actions.pop_front();
+  }
+}
index 679ccd982d4ca44760f907cb35cbe93cfd598bd2..fb11512a2707142ddef6f3353927694b0deeb78f 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef JUMPARTIFACT_DOT_COM_DEMO_0_SCREEN_H_
 #define JUMPARTIFACT_DOT_COM_DEMO_0_SCREEN_H_
 
+#include <deque>
 #include <memory>
 #include <vector>
 
@@ -31,12 +32,30 @@ class Screen {
 
  protected:
   Screen(std::weak_ptr<ScreenStack> stack);
-
- private:
   std::weak_ptr<ScreenStack> stack;
 };
 
 class ScreenStack {
+ private:
+  enum Action { PUSH_SCREEN, POP_SCREEN, NOP };
+
+  struct PendingAction {
+    PendingAction();
+    PendingAction(Action action);
+    PendingAction(Screen::Ptr&&);
+
+    // No copy.
+    PendingAction(const PendingAction&) = delete;
+    PendingAction& operator=(const PendingAction&) = delete;
+
+    // Allow move.
+    PendingAction(PendingAction&&) = default;
+    PendingAction& operator=(PendingAction&&) = default;
+
+    Screen::Ptr screen;
+    Action action;
+  };
+
  public:
   using Ptr = std::shared_ptr<ScreenStack>;
   using Weak = std::weak_ptr<ScreenStack>;
@@ -64,8 +83,11 @@ class ScreenStack {
  private:
   ScreenStack();
 
+  void handle_pending_actions();
+
   Weak self_weak;
   std::vector<Screen::Ptr> stack;
+  std::deque<PendingAction> actions;
 };
 
 template <typename SubScreen>