From 178fecf1e74ff3f015d29f07dfd4e6e2dffb6eb8 Mon Sep 17 00:00:00 2001 From: Eric McDaniel Date: Sun, 21 Jun 2026 21:26:25 -0500 Subject: [PATCH 1/8] Setup new selection in system state --- include/display/display.h | 1 + include/engine/state-manager.h | 6 ++++++ include/games/reflex/driver.h | 21 +++++++++++++++++++++ include/games/reflex/state.h | 31 +++++++++++++++++++++++++++++++ 4 files changed, 59 insertions(+) create mode 100644 include/games/reflex/driver.h create mode 100644 include/games/reflex/state.h diff --git a/include/display/display.h b/include/display/display.h index ce77513..d3be0ee 100644 --- a/include/display/display.h +++ b/include/display/display.h @@ -46,6 +46,7 @@ namespace Display void drawRecallGameHud(); void drawPhaseEvasionGameHud(); void drawChainReactionGameHud(); + void drawReflexGameHud(); void drawDemoGameHud(); void drawCanvasSceneHud(); void drawUnconnectedControllerScreen(); diff --git a/include/engine/state-manager.h b/include/engine/state-manager.h index 4cd296c..6bec2d1 100644 --- a/include/engine/state-manager.h +++ b/include/engine/state-manager.h @@ -3,6 +3,7 @@ #include "games/recall/state.h" #include "games/phase-evasion/state.h" #include "games/chain-reaction/state.h" +#include "games/reflex/state.h" #include "games/demo/state.h" #include "scenes/canvas/state.h" @@ -23,6 +24,7 @@ namespace Engine GameRecall, GamePhaseEvasion, GameChainReaction, + GameReflex, GameDemo, SceneCanvas, NoControllerConnected, @@ -41,6 +43,7 @@ namespace Engine Recall, PhaseEvasion, ChainReaction, + Reflex, Demo, COUNT }; @@ -64,6 +67,7 @@ namespace Engine recallGameState{ctx}, phaseEvasionGameState{ctx}, chainReactionGameState{ctx}, + reflexGameState{ctx}, systemState{SystemState::Initialize}, userMainMenuChoice{MainMenuSelection::Games}, userGameChoice{GameSelection::Recall}, @@ -95,6 +99,7 @@ namespace Engine Games::Recall::GameState &getRecallGameState() { return recallGameState; } Games::PhaseEvasion::GameState &getPhaseEvasionGameState() { return phaseEvasionGameState; } Games::ChainReaction::GameState &getChainReactionGameState() { return chainReactionGameState; } + Games::Reflex::GameState &getReflexGameState() { return reflexGameState; } Games::Demo::GameState &getDemoGameState() { return demoGameState; } Scenes::Canvas::SceneState &getCanvasSceneState() { return canvasSceneState; } @@ -110,6 +115,7 @@ namespace Engine Games::Recall::GameState recallGameState; Games::PhaseEvasion::GameState phaseEvasionGameState; Games::ChainReaction::GameState chainReactionGameState; + Games::Reflex::GameState reflexGameState; Games::Demo::GameState demoGameState; Scenes::Canvas::SceneState canvasSceneState; diff --git a/include/games/reflex/driver.h b/include/games/reflex/driver.h new file mode 100644 index 0000000..5d1180c --- /dev/null +++ b/include/games/reflex/driver.h @@ -0,0 +1,21 @@ +#pragma once + +#include "engine/layer.h" +#include "engine/timer.h" +#include "core/context-manager.h" + +namespace Games::Reflex +{ + class Driver : public Engine::Layer, private Engine::Timer + { + public: + Driver(SystemCore::ContextManager *ctx); + ~Driver() { state.reset(); } + void nextEvent() override; + void reset(); + + private: + SystemCore::ContextManager *contextManager; + GameState &state; + }; +} \ No newline at end of file diff --git a/include/games/reflex/state.h b/include/games/reflex/state.h new file mode 100644 index 0000000..6dfe704 --- /dev/null +++ b/include/games/reflex/state.h @@ -0,0 +1,31 @@ +#pragma once + +#include + +namespace SystemCore +{ + class ContextManager; +} + +namespace Games::Reflex +{ + enum class Actions + { + Startup, + GameOver + }; + + class GameState + { + public: + GameState(SystemCore::ContextManager *ctx) : contextManager{ctx} {} + + Actions current = Actions::Startup; + static constexpr const char *memoryKeyName = "high_reflex"; + + void reset(); + + private: + SystemCore::ContextManager *contextManager; + }; +} \ No newline at end of file From 97a9bd15530ede4c76fa970409dac6f9d2c5ea00 Mon Sep 17 00:00:00 2001 From: Eric McDaniel Date: Sun, 21 Jun 2026 21:56:24 -0500 Subject: [PATCH 2/8] Complete system support for new app --- include/games/reflex/driver.h | 2 +- include/games/reflex/state.h | 2 +- src/core/context-manager.cpp | 8 ++++++++ src/display/display.cpp | 11 +++++++++++ src/engine/engine.cpp | 1 + src/engine/state-manager.cpp | 1 + src/games/reflex/driver.cpp | 29 +++++++++++++++++++++++++++++ 7 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 src/games/reflex/driver.cpp diff --git a/include/games/reflex/driver.h b/include/games/reflex/driver.h index 5d1180c..b682c53 100644 --- a/include/games/reflex/driver.h +++ b/include/games/reflex/driver.h @@ -12,7 +12,7 @@ namespace Games::Reflex Driver(SystemCore::ContextManager *ctx); ~Driver() { state.reset(); } void nextEvent() override; - void reset(); + void reset() {} private: SystemCore::ContextManager *contextManager; diff --git a/include/games/reflex/state.h b/include/games/reflex/state.h index 6dfe704..ae211a5 100644 --- a/include/games/reflex/state.h +++ b/include/games/reflex/state.h @@ -23,7 +23,7 @@ namespace Games::Reflex Actions current = Actions::Startup; static constexpr const char *memoryKeyName = "high_reflex"; - void reset(); + void reset() {} private: SystemCore::ContextManager *contextManager; diff --git a/src/core/context-manager.cpp b/src/core/context-manager.cpp index b726813..8c57826 100644 --- a/src/core/context-manager.cpp +++ b/src/core/context-manager.cpp @@ -3,6 +3,7 @@ #include "games/recall/driver.h" #include "games/phase-evasion/driver.h" #include "games/chain-reaction/driver.h" +#include "games/reflex/driver.h" #include "games/demo/driver.h" #include "scenes/canvas/driver.h" #include "logger.h" @@ -116,6 +117,9 @@ namespace SystemCore case Engine::GameSelection::ChainReaction: stateManager.setNext(Engine::SystemState::GameChainReaction); break; + case Engine::GameSelection::Reflex: + stateManager.setNext(Engine::SystemState::GameReflex); + break; case Engine::GameSelection::Demo: stateManager.setNext(Engine::SystemState::GameDemo); break; @@ -185,6 +189,10 @@ namespace SystemCore application = new Games::ChainReaction::Driver{this}; logf("Transitioning to Chain Reaction (Game)"); break; + case Engine::SystemState::GameReflex: + application = new Games::Reflex::Driver{this}; + logf("Transitioning to Reflex (Game)"); + break; case Engine::SystemState::GameDemo: application = new Games::Demo::Driver{this}; logf("Transitioning to Demo (Game)"); diff --git a/src/display/display.cpp b/src/display/display.cpp index 364ed72..0acce69 100644 --- a/src/display/display.cpp +++ b/src/display/display.cpp @@ -229,6 +229,17 @@ namespace Display display.display(); } + void OledDisplay::drawReflexGameHud() + { + + display.clearDisplay(); + drawHeader("Reflex"); + + const auto reflexState = contextManager->stateManager.getReflexGameState(); + + display.display(); + } + void OledDisplay::drawCanvasSceneHud() { display.clearDisplay(); diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index 63579e5..a9198a6 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -45,6 +45,7 @@ namespace Engine case SystemState::GameRecall: case SystemState::GamePhaseEvasion: case SystemState::GameChainReaction: + case SystemState::GameReflex: case SystemState::GameDemo: case SystemState::SceneCanvas: contextManager.application->nextEvent(); diff --git a/src/engine/state-manager.cpp b/src/engine/state-manager.cpp index d82dced..8ebff64 100644 --- a/src/engine/state-manager.cpp +++ b/src/engine/state-manager.cpp @@ -51,6 +51,7 @@ namespace Engine "Recall", "Phase Evasion", "Chain Reaction", + "Reflex", "Demo"}; return gameNames[index]; } diff --git a/src/games/reflex/driver.cpp b/src/games/reflex/driver.cpp new file mode 100644 index 0000000..fac4c58 --- /dev/null +++ b/src/games/reflex/driver.cpp @@ -0,0 +1,29 @@ +#include "games/reflex/driver.h" +#include "logger.h" + +namespace Games::Reflex +{ + Driver::Driver(SystemCore::ContextManager *ctx) : contextManager{ctx}, + state{ctx->stateManager.getReflexGameState()} + { + reset(); + wait(500); + } + + void Driver::nextEvent() + { + switch (state.current) + { + case Actions::Startup: + if (isReady()) + { + reset(); + state.current = Actions::GameOver; + log("Starting new game."); + } + break; + default: + break; + } + } +} \ No newline at end of file From 8b06740faf9207f4e92db2b571f3cf1af9f19a57 Mon Sep 17 00:00:00 2001 From: Eric McDaniel Date: Mon, 22 Jun 2026 22:22:48 -0500 Subject: [PATCH 3/8] Setup rough debugger for OLED display --- include/display/display.h | 2 + include/display/oled-serialization.h | 13 ++++++ src/display/display.cpp | 45 ++++++++++++++++++- src/display/oled-serialization.cpp | 52 ++++++++++++++++++++++ tools/led_gui/virtualization.py | 65 +++++++++++++++++++++++----- 5 files changed, 164 insertions(+), 13 deletions(-) create mode 100644 include/display/oled-serialization.h create mode 100644 src/display/oled-serialization.cpp diff --git a/include/display/display.h b/include/display/display.h index d3be0ee..732481b 100644 --- a/include/display/display.h +++ b/include/display/display.h @@ -10,6 +10,7 @@ #endif #include "display/display-images.h" +#include "display/oled-serialization.h" namespace SystemCore { @@ -37,6 +38,7 @@ namespace Display char selectedOption(uint8_t index, uint8_t selectedOptionIndex) { return index == selectedOptionIndex ? '>' : ' '; }; int16_t calculateCenterText(const char *text); + void debugUpdateDisplay(const char *format, ...); void drawHeader(const char *message); void drawBootScreen(); diff --git a/include/display/oled-serialization.h b/include/display/oled-serialization.h new file mode 100644 index 0000000..900e9b1 --- /dev/null +++ b/include/display/oled-serialization.h @@ -0,0 +1,13 @@ +#pragma once + +#ifdef VIRTUALIZATION + +namespace Display +{ + // Send OLED text update to serial port (only if content changed) + // Format: 0xBB 0x66 [2-byte length] [text data] + void sendOledUpdate(const char *text); + void serializeOledText(const char *text); +} + +#endif diff --git a/src/display/display.cpp b/src/display/display.cpp index 0acce69..d952d54 100644 --- a/src/display/display.cpp +++ b/src/display/display.cpp @@ -1,4 +1,5 @@ #include +#include #include "display/display.h" #include "core/context-manager.h" @@ -85,6 +86,18 @@ namespace Display display.print(message); } + void OledDisplay::debugUpdateDisplay(const char *format, ...) + { +#ifdef VIRTUALIZATION + char oledBuffer[256] = ""; + va_list args; + va_start(args, format); + vsnprintf(oledBuffer, sizeof(oledBuffer), format, args); + va_end(args); + Display::sendOledUpdate(oledBuffer); +#endif + } + void OledDisplay::drawBootScreen() { display.clearDisplay(); @@ -115,6 +128,9 @@ namespace Display display.print(selectedOption(1, selectedOptionIndex)); display.print(" Scenes"); + debugUpdateDisplay(" Main Menu\n%c Games\n%c Scenes", + selectedOption(0, selectedOptionIndex), selectedOption(1, selectedOptionIndex)); + display.display(); } @@ -140,6 +156,15 @@ namespace Display display.print(nameBuffer); } + char oledBuffer[256] = ""; + int offset = snprintf(oledBuffer, sizeof(oledBuffer), "Games Menu (%d/%d)", currentPage + 1, (numGames + itemsPerPage - 1) / itemsPerPage); + for (int i = startIndex; i < endIndex; ++i) + { + offset += snprintf(oledBuffer + offset, sizeof(oledBuffer) - offset, "\n%c %s", + selectedOption(i, selectedOptionIndex), contextManager->stateManager.printGameName(i)); + } + debugUpdateDisplay("%s", oledBuffer); + display.display(); } @@ -155,6 +180,9 @@ namespace Display sprintf(nameBuffer, "%c %s", selectedOption(0, selectedOptionIndex), contextManager->stateManager.printSceneName(0)); display.print(nameBuffer); + debugUpdateDisplay(" Scenes Menu\n%c %s", + selectedOption(0, selectedOptionIndex), contextManager->stateManager.printSceneName(0)); + display.display(); } @@ -169,6 +197,9 @@ namespace Display display.setCursor(0, 24); display.print("High Score: -"); + debugUpdateDisplay(" Demo\nCurrent Score: %u\nHigh Score: -", + contextManager->stateManager.getDemoGameState().currentScore); + display.display(); } @@ -186,6 +217,8 @@ namespace Display display.setCursor(0, 24); display.printf("High Score: %u", highScore + 1); + debugUpdateDisplay(" Recall\nRound: %u\nHigh Score: %u", round + 1, highScore + 1); + display.display(); } @@ -210,6 +243,9 @@ namespace Display display.setCursor(DISPLAY_WIDTH / 2 + 4, 24); display.printf(" High: %u", highScore); + debugUpdateDisplay(" Phase Evasion\nFlares: %u Total: %u\nGems: %u High: %u", + flaresEvaded, totalScore, gemsCaptured, highScore); + display.display(); } @@ -226,17 +262,20 @@ namespace Display display.setCursor(0, 24); display.printf("Total: %u", reactions); + debugUpdateDisplay(" Chain Reaction\nReactions: %u\nTotal: %u", reactions, reactions); + display.display(); } void OledDisplay::drawReflexGameHud() { - display.clearDisplay(); drawHeader("Reflex"); const auto reflexState = contextManager->stateManager.getReflexGameState(); + debugUpdateDisplay(" Reflex"); + display.display(); } @@ -251,6 +290,8 @@ namespace Display display.setCursor(0, 24); display.print(colorBuffer); + debugUpdateDisplay(" Canvas\nRGB: (%u, %u, %u)", color.r, color.g, color.b); + display.display(); } @@ -270,6 +311,8 @@ namespace Display display.setCursor(startingX, 16); display.print("not connected"); + debugUpdateDisplay(" LumenLab\n%s controller\nnot connected", SystemCore::Configuration::psControllerType().c_str()); + display.display(); } } \ No newline at end of file diff --git a/src/display/oled-serialization.cpp b/src/display/oled-serialization.cpp new file mode 100644 index 0000000..e162adf --- /dev/null +++ b/src/display/oled-serialization.cpp @@ -0,0 +1,52 @@ +#ifdef VIRTUALIZATION + +#include +#include +#include "display/oled-serialization.h" + +namespace Display +{ + static uint32_t simpleHash(const char *str) + { + uint32_t hash = 5381; + int c; + while ((c = *str++)) + hash = ((hash << 5) + hash) + c; + return hash; + } + + static uint32_t previousHash = 0; + + void serializeOledText(const char *text) + { + if (!text) + return; + + size_t len = strlen(text); + if (len > 65535) + len = 65535; + + Serial.write(0xBB); + Serial.write(0x66); + Serial.write((uint8_t)(len >> 8)); + Serial.write((uint8_t)(len & 0xFF)); + + Serial.write(reinterpret_cast(text), len); + } + + void sendOledUpdate(const char *text) + { + if (!text) + return; + + uint32_t currentHash = simpleHash(text); + + if (currentHash != previousHash) + { + previousHash = currentHash; + serializeOledText(text); + } + } +} + +#endif diff --git a/tools/led_gui/virtualization.py b/tools/led_gui/virtualization.py index fee839f..1bcd01a 100644 --- a/tools/led_gui/virtualization.py +++ b/tools/led_gui/virtualization.py @@ -79,6 +79,8 @@ def __init__(self, **kwargs): 2.0 / self.window_size[1], ) self.led_lock = threading.Lock() + self.oled_text = "" + self.OLED_SYNC_BYTES = b'\xBB\x66' self.serial_thread = threading.Thread(target=self.read_serial, daemon=True) self.serial_thread.start() @@ -104,6 +106,18 @@ def __init__(self, **kwargs): color=(160, 160, 160, 160), width=300 ) + self.oled_label = pyglet.text.Label( + "", + font_name='Consolas', + font_size=16, + x=50, + y=self.window_size[1] - 100, + anchor_x='left', + anchor_y='top', + color=(255, 255, 255, 255), + width=400, + multiline=True + ) def compute_led_positions(self): led_radius = 11 @@ -154,20 +168,45 @@ def normalize_positions(self, raw_positions): def read_serial(self): def process_buffer(): - """Extract complete frames from buffer and update LED colors.""" + """Extract complete OLED and LED frames from buffer.""" nonlocal buffer while True: - idx = buffer.find(self.SYNC_BYTES) - if idx == -1: - break # no sync bytes found yet - if len(buffer) < idx + 2 + self.FRAME_SIZE: - break # incomplete frame - start = idx + 2 - frame = buffer[start:start + self.FRAME_SIZE] - buffer = buffer[start + self.FRAME_SIZE:] - with self.led_lock: - colors = np.frombuffer(frame, dtype=np.uint8).reshape(-1, 3) / 255.0 - self.led_colors[:] = colors + oled_idx = buffer.find(self.OLED_SYNC_BYTES) + led_idx = buffer.find(self.SYNC_BYTES) + + if oled_idx != -1 and (led_idx == -1 or oled_idx < led_idx): + if len(buffer) < oled_idx + 4: + break + + length = (buffer[oled_idx + 2] << 8) | buffer[oled_idx + 3] + + if len(buffer) < oled_idx + 4 + length: + break + + oled_data = buffer[oled_idx + 4:oled_idx + 4 + length] + try: + oled_text = oled_data.decode('utf-8') + with self.led_lock: + self.oled_text = oled_text + logging.info(f"OLED: {repr(oled_text)}") + except UnicodeDecodeError as e: + logging.warning(f"Failed to decode OLED text: {e}") + + buffer = buffer[oled_idx + 4 + length:] + + elif led_idx != -1: + if len(buffer) < led_idx + 2 + self.FRAME_SIZE: + break # incomplete frame + + start = led_idx + 2 + frame = buffer[start:start + self.FRAME_SIZE] + buffer = buffer[start + self.FRAME_SIZE:] + + with self.led_lock: + colors = np.frombuffer(frame, dtype=np.uint8).reshape(-1, 3) / 255.0 + self.led_colors[:] = colors + else: + break buffer = bytearray() while True: @@ -191,10 +230,12 @@ def on_render(self, time, frametime): with self.led_lock: self.vbo_positions.write(self.positions.tobytes()) self.vbo_colors.write(self.led_colors.tobytes()) + self.oled_label.text = self.oled_text self.prog['pixel_size'].value = self.pixel_size self.vao.render(instances=self.num_leds) self.title.draw() self.description.draw() + self.oled_label.draw() def start_led_virtualization(window_size, num_leds, port, baud_rate): From 3cda60e6ce9441934044d243a9f679cfa2641613 Mon Sep 17 00:00:00 2001 From: Eric McDaniel Date: Mon, 22 Jun 2026 22:41:02 -0500 Subject: [PATCH 4/8] Update display on Reflex start --- include/games/reflex/driver.h | 2 +- src/display/display.cpp | 3 +++ src/games/reflex/driver.cpp | 5 +++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/include/games/reflex/driver.h b/include/games/reflex/driver.h index b682c53..5d1180c 100644 --- a/include/games/reflex/driver.h +++ b/include/games/reflex/driver.h @@ -12,7 +12,7 @@ namespace Games::Reflex Driver(SystemCore::ContextManager *ctx); ~Driver() { state.reset(); } void nextEvent() override; - void reset() {} + void reset(); private: SystemCore::ContextManager *contextManager; diff --git a/src/display/display.cpp b/src/display/display.cpp index d952d54..4ca3ef7 100644 --- a/src/display/display.cpp +++ b/src/display/display.cpp @@ -53,6 +53,9 @@ namespace Display case Engine::SystemState::GameChainReaction: drawChainReactionGameHud(); break; + case Engine::SystemState::GameReflex: + drawReflexGameHud(); + break; case Engine::SystemState::SceneCanvas: drawCanvasSceneHud(); break; diff --git a/src/games/reflex/driver.cpp b/src/games/reflex/driver.cpp index fac4c58..9dbf178 100644 --- a/src/games/reflex/driver.cpp +++ b/src/games/reflex/driver.cpp @@ -26,4 +26,9 @@ namespace Games::Reflex break; } } + + void Driver::reset() + { + contextManager->stateManager.displayShouldUpdate = true; + } } \ No newline at end of file From 3b697e29dae04d7bf975dcb1bd2380478703efca Mon Sep 17 00:00:00 2001 From: Eric McDaniel Date: Tue, 23 Jun 2026 19:56:16 -0500 Subject: [PATCH 5/8] Remove redundant includes --- include/core/configuration.h | 1 - include/logger.h | 2 -- src/lights/led-luminance.cpp | 2 -- 3 files changed, 5 deletions(-) diff --git a/include/core/configuration.h b/include/core/configuration.h index acd4d00..e6e6718 100644 --- a/include/core/configuration.h +++ b/include/core/configuration.h @@ -1,6 +1,5 @@ #pragma once -#include #include #include diff --git a/include/logger.h b/include/logger.h index 3c11c7a..f543ffd 100644 --- a/include/logger.h +++ b/include/logger.h @@ -1,7 +1,5 @@ #pragma once -#include - /* Interesting compiler optimization below, when building with the DEBUG flag on it prints to the serial monitor as normal, but when building in RELEASE diff --git a/src/lights/led-luminance.cpp b/src/lights/led-luminance.cpp index f006dca..e78cc92 100644 --- a/src/lights/led-luminance.cpp +++ b/src/lights/led-luminance.cpp @@ -1,5 +1,3 @@ -#include - #include "lights/led-luminance.h" namespace Lights From 8085c1598b3e84ce2a0346f04848c82363765596 Mon Sep 17 00:00:00 2001 From: Eric McDaniel Date: Tue, 23 Jun 2026 20:37:03 -0500 Subject: [PATCH 6/8] Create Signal entity --- include/games/reflex/driver.h | 3 +++ include/games/reflex/signal.h | 14 ++++++++++++++ include/games/reflex/state.h | 1 + src/games/reflex/driver.cpp | 5 ++++- src/games/reflex/signal.cpp | 6 ++++++ 5 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 include/games/reflex/signal.h create mode 100644 src/games/reflex/signal.cpp diff --git a/include/games/reflex/driver.h b/include/games/reflex/driver.h index 5d1180c..54f9c58 100644 --- a/include/games/reflex/driver.h +++ b/include/games/reflex/driver.h @@ -3,6 +3,7 @@ #include "engine/layer.h" #include "engine/timer.h" #include "core/context-manager.h" +#include "games/reflex/signal.h" namespace Games::Reflex { @@ -17,5 +18,7 @@ namespace Games::Reflex private: SystemCore::ContextManager *contextManager; GameState &state; + + Signal signal; }; } \ No newline at end of file diff --git a/include/games/reflex/signal.h b/include/games/reflex/signal.h new file mode 100644 index 0000000..f121342 --- /dev/null +++ b/include/games/reflex/signal.h @@ -0,0 +1,14 @@ +#pragma once + +namespace Games::Reflex +{ + class Signal + { + public: + Signal(); + ~Signal() = default; + + private: + float position; + }; +} \ No newline at end of file diff --git a/include/games/reflex/state.h b/include/games/reflex/state.h index ae211a5..200580c 100644 --- a/include/games/reflex/state.h +++ b/include/games/reflex/state.h @@ -12,6 +12,7 @@ namespace Games::Reflex enum class Actions { Startup, + ActiveGame, GameOver }; diff --git a/src/games/reflex/driver.cpp b/src/games/reflex/driver.cpp index 9dbf178..118c38e 100644 --- a/src/games/reflex/driver.cpp +++ b/src/games/reflex/driver.cpp @@ -1,4 +1,5 @@ #include "games/reflex/driver.h" +#include "games/reflex/signal.h" #include "logger.h" namespace Games::Reflex @@ -18,10 +19,12 @@ namespace Games::Reflex if (isReady()) { reset(); - state.current = Actions::GameOver; + state.current = Actions::ActiveGame; log("Starting new game."); } break; + case Actions::ActiveGame: + break; default: break; } diff --git a/src/games/reflex/signal.cpp b/src/games/reflex/signal.cpp new file mode 100644 index 0000000..21524cf --- /dev/null +++ b/src/games/reflex/signal.cpp @@ -0,0 +1,6 @@ +#include "games/reflex/signal.h" + +namespace Games::Reflex +{ + Signal::Signal() : position{0.0f} {} +} \ No newline at end of file From f4730f575d01c50edf1873b69feeb1d98e7f6fbe Mon Sep 17 00:00:00 2001 From: Eric McDaniel Date: Wed, 24 Jun 2026 21:54:35 -0500 Subject: [PATCH 7/8] Define signal attributes, render first animation --- include/games/reflex/driver.h | 3 +++ include/games/reflex/signal.h | 13 +++++++++---- src/games/reflex/driver.cpp | 14 +++++++++++++- src/games/reflex/signal.cpp | 3 ++- 4 files changed, 27 insertions(+), 6 deletions(-) diff --git a/include/games/reflex/driver.h b/include/games/reflex/driver.h index 54f9c58..f51bb1b 100644 --- a/include/games/reflex/driver.h +++ b/include/games/reflex/driver.h @@ -12,7 +12,10 @@ namespace Games::Reflex public: Driver(SystemCore::ContextManager *ctx); ~Driver() { state.reset(); } + static constexpr uint16_t signalWidth = 5; + static constexpr float signalSpeed = 0.25f; void nextEvent() override; + void renderSignal(); void reset(); private: diff --git a/include/games/reflex/signal.h b/include/games/reflex/signal.h index f121342..4f23312 100644 --- a/include/games/reflex/signal.h +++ b/include/games/reflex/signal.h @@ -1,14 +1,19 @@ #pragma once +#include "core/context-manager.h" +#include "player/player.h" + namespace Games::Reflex { - class Signal + class Signal : public ::Player::BasePlayer { public: - Signal(); + Signal(SystemCore::ContextManager *ctx, uint16_t width, float _speed); ~Signal() = default; + void advance() { setPosition(positionPrecise += speed); } + private: - float position; + float speed; }; -} \ No newline at end of file +} diff --git a/src/games/reflex/driver.cpp b/src/games/reflex/driver.cpp index 118c38e..fa42221 100644 --- a/src/games/reflex/driver.cpp +++ b/src/games/reflex/driver.cpp @@ -5,7 +5,8 @@ namespace Games::Reflex { Driver::Driver(SystemCore::ContextManager *ctx) : contextManager{ctx}, - state{ctx->stateManager.getReflexGameState()} + state{ctx->stateManager.getReflexGameState()}, + signal{ctx, signalWidth, signalSpeed} { reset(); wait(500); @@ -24,6 +25,8 @@ namespace Games::Reflex } break; case Actions::ActiveGame: + signal.advance(); + renderSignal(); break; default: break; @@ -34,4 +37,13 @@ namespace Games::Reflex { contextManager->stateManager.displayShouldUpdate = true; } + + void Driver::renderSignal() + { + for (uint16_t i = 0; i < signal.width; ++i) + { + uint16_t index = (signal.getPosition() + i) % SystemCore::Configuration::numLeds(); + contextManager->leds.buffer[index] = Lights::ColorCode::MenuUnselected; + } + } } \ No newline at end of file diff --git a/src/games/reflex/signal.cpp b/src/games/reflex/signal.cpp index 21524cf..e8124f6 100644 --- a/src/games/reflex/signal.cpp +++ b/src/games/reflex/signal.cpp @@ -2,5 +2,6 @@ namespace Games::Reflex { - Signal::Signal() : position{0.0f} {} + Signal::Signal(SystemCore::ContextManager *ctx, uint16_t width, float _speed) : ::Player::BasePlayer{ctx, width}, + speed{_speed} {} } \ No newline at end of file From 5df96796b09a435010c8f5ce11506f721c975b0c Mon Sep 17 00:00:00 2001 From: Eric McDaniel Date: Thu, 25 Jun 2026 21:40:00 -0500 Subject: [PATCH 8/8] Relax game start --- include/games/reflex/driver.h | 4 ++-- include/games/reflex/state.h | 1 + src/games/reflex/driver.cpp | 11 +++++++++-- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/include/games/reflex/driver.h b/include/games/reflex/driver.h index f51bb1b..d2c560e 100644 --- a/include/games/reflex/driver.h +++ b/include/games/reflex/driver.h @@ -12,8 +12,8 @@ namespace Games::Reflex public: Driver(SystemCore::ContextManager *ctx); ~Driver() { state.reset(); } - static constexpr uint16_t signalWidth = 5; - static constexpr float signalSpeed = 0.25f; + static constexpr uint16_t signalWidth = 7; + static constexpr float signalSpeed = 1.0f; void nextEvent() override; void renderSignal(); void reset(); diff --git a/include/games/reflex/state.h b/include/games/reflex/state.h index 200580c..94f00d0 100644 --- a/include/games/reflex/state.h +++ b/include/games/reflex/state.h @@ -12,6 +12,7 @@ namespace Games::Reflex enum class Actions { Startup, + Ready, ActiveGame, GameOver }; diff --git a/src/games/reflex/driver.cpp b/src/games/reflex/driver.cpp index fa42221..2f29e42 100644 --- a/src/games/reflex/driver.cpp +++ b/src/games/reflex/driver.cpp @@ -9,7 +9,6 @@ namespace Games::Reflex signal{ctx, signalWidth, signalSpeed} { reset(); - wait(500); } void Driver::nextEvent() @@ -20,10 +19,18 @@ namespace Games::Reflex if (isReady()) { reset(); - state.current = Actions::ActiveGame; + state.current = Actions::Ready; + wait(1000); log("Starting new game."); } break; + case Actions::Ready: + if (isReady()) + { + state.current = Actions::ActiveGame; + } + renderSignal(); + break; case Actions::ActiveGame: signal.advance(); renderSignal();