From 99bf19e35a9bc5a1fc0a71b3a26aa4dd9e3c7937 Mon Sep 17 00:00:00 2001 From: Eric McDaniel Date: Mon, 9 Feb 2026 18:22:21 -0600 Subject: [PATCH 1/9] Preferences memory setup --- include/core/context-manager.h | 3 +++ src/engine/engine.cpp | 8 ++++++++ 2 files changed, 11 insertions(+) diff --git a/include/core/context-manager.h b/include/core/context-manager.h index e35106f..3098325 100644 --- a/include/core/context-manager.h +++ b/include/core/context-manager.h @@ -1,5 +1,7 @@ #pragma once +#include + #include "engine/layer.h" #include "engine/state-manager.h" #include "player/controller.h" @@ -22,6 +24,7 @@ namespace SystemCore Player::Controller controller; Lights::LedStrip leds; Display::OledDisplay display; + Preferences memory; Display::MenuTileNavigation menuNav; void navigateMainMenu(); diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index 25dcce2..e34b6df 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -1,6 +1,7 @@ #include #include +#include #include "engine/engine.h" #include "lights/color.h" #include "display/menu-navigation.h" @@ -108,6 +109,13 @@ namespace Engine lastRender = micros(); log("Startup process completed. Transitioning to Main Menu"); } + +#ifdef RELEASE + contextManager.memory.begin("lumenlab", false); +#else + contextManager.memory.begin("lumenlab-development", false); +#endif + randomSeed(esp_random()); } From db07ff11c4e90cee9d2bb8f653819fc929901624 Mon Sep 17 00:00:00 2001 From: Eric McDaniel Date: Mon, 9 Feb 2026 19:00:12 -0600 Subject: [PATCH 2/9] Programatically calculate total and high score --- include/games/phase-evasion/driver.h | 1 + include/games/phase-evasion/state.h | 8 +++++++- src/display/display.cpp | 6 ++++-- src/games/phase-evasion/driver.cpp | 17 +++++++++++++++++ 4 files changed, 29 insertions(+), 3 deletions(-) diff --git a/include/games/phase-evasion/driver.h b/include/games/phase-evasion/driver.h index 0ecb6ba..ada133f 100644 --- a/include/games/phase-evasion/driver.h +++ b/include/games/phase-evasion/driver.h @@ -41,6 +41,7 @@ namespace Games::PhaseEvasion float gameOverPhaseOffset = 0.0f; void getUpdates(); + void checkIfHighScore(); void renderPlayer(); void renderFlare(); void renderGem(); diff --git a/include/games/phase-evasion/state.h b/include/games/phase-evasion/state.h index 7e31976..19a6499 100644 --- a/include/games/phase-evasion/state.h +++ b/include/games/phase-evasion/state.h @@ -21,6 +21,12 @@ namespace Games::PhaseEvasion uint16_t gemsCaptured; uint16_t highScore; Actions current = Actions::Startup; - void reset() { highScore = flaresEvaded = gemsCaptured = 0; } + + void reset() + { + highScore = flaresEvaded = gemsCaptured = 0; + // highScore = contextManager->memory.getUInt("phase-evasion-high-score"); + } + uint16_t calculateTotalScore() const { return flaresEvaded + (2 * gemsCaptured); } }; } \ No newline at end of file diff --git a/src/display/display.cpp b/src/display/display.cpp index 3fcb149..491de47 100644 --- a/src/display/display.cpp +++ b/src/display/display.cpp @@ -187,6 +187,8 @@ namespace Display { const auto flaresEvaded = contextManager->stateManager.getPhaseEvasionGameState().flaresEvaded; const auto gemsCaptured = contextManager->stateManager.getPhaseEvasionGameState().gemsCaptured; + const auto totalScore = contextManager->stateManager.getPhaseEvasionGameState().calculateTotalScore(); + const auto highScore = contextManager->stateManager.getPhaseEvasionGameState().highScore; display.clearDisplay(); drawHeader("Phase Evasion"); @@ -194,12 +196,12 @@ namespace Display display.setCursor(0, 16); display.printf("Flares: %u", flaresEvaded); display.setCursor(DISPLAY_WIDTH / 2 + 4, 16); - display.printf("Total: %u", (flaresEvaded + (2 * gemsCaptured))); + display.printf("Total: %u", totalScore); display.setCursor(0, 24); display.printf(" Gems: %u", gemsCaptured); display.setCursor(DISPLAY_WIDTH / 2 + 4, 24); - display.printf(" High: %u", (flaresEvaded + (2 * gemsCaptured))); + display.printf(" High: %u", highScore); display.display(); } diff --git a/src/games/phase-evasion/driver.cpp b/src/games/phase-evasion/driver.cpp index 98e2e4d..a8ca804 100644 --- a/src/games/phase-evasion/driver.cpp +++ b/src/games/phase-evasion/driver.cpp @@ -1,3 +1,4 @@ +#include #include "games/phase-evasion/driver.h" #include "player/controller.h" #include "logger.h" @@ -34,6 +35,7 @@ namespace Games::PhaseEvasion assessDifficulty(); checkCollision(); checkGemCapture(); + checkIfHighScore(); renderFlare(); renderGem(); renderPlayer(); @@ -194,6 +196,21 @@ namespace Games::PhaseEvasion } } + void Driver::checkIfHighScore() + { + const GameState state = contextManager->stateManager.getPhaseEvasionGameState(); + + const uint16_t highScore = state.highScore; + const uint16_t currentScore = state.calculateTotalScore(); + + if (currentScore > highScore) + { + contextManager->stateManager.getPhaseEvasionGameState().highScore = currentScore; + contextManager->stateManager.displayShouldUpdate = true; + // contextManager->memory.putUInt("phase-evasion-high-score", contextManager->stateManager.getPhaseEvasionGameState().highScore); + } + } + void Driver::muzzleFlash() { for (uint16_t i = 0; i < SystemCore::Configuration::numLeds; ++i) From 95de54471eb944c6debd981210816dcef05f7e09 Mon Sep 17 00:00:00 2001 From: Eric McDaniel Date: Mon, 9 Feb 2026 20:29:40 -0600 Subject: [PATCH 3/9] Write Phase Evasion high score to non-volatile memory --- include/engine/state-manager.h | 17 +++++++++++++--- include/games/phase-evasion/state.h | 20 ++++++++++++------- src/core/context-manager.cpp | 2 +- src/engine/engine.cpp | 2 +- src/engine/state-manager.cpp | 1 + src/games/phase-evasion/driver.cpp | 3 +-- src/games/phase-evasion/flare-manager.cpp | 1 + src/games/phase-evasion/state.cpp | 24 +++++++++++++++++++++++ 8 files changed, 56 insertions(+), 14 deletions(-) create mode 100644 src/games/phase-evasion/state.cpp diff --git a/include/engine/state-manager.h b/include/engine/state-manager.h index 5f3e67c..c55c1a2 100644 --- a/include/engine/state-manager.h +++ b/include/engine/state-manager.h @@ -5,6 +5,12 @@ #include "games/demo/state.h" #include "scenes/canvas/state.h" +namespace SystemCore +{ + // forward declaration because of ContextManager/OledDisplay circular dependency + class ContextManager; +} + namespace Engine { enum class SystemState @@ -51,9 +57,13 @@ namespace Engine class StateManager { public: - StateManager() : systemState{SystemState::Initialize}, - userMainMenuChoice{MainMenuSelection::Games}, - userGameChoice{GameSelection::Recall} {} + StateManager(SystemCore::ContextManager *ctx) : contextManager{ctx}, + phaseEvasionGameState{ctx}, + systemState{SystemState::Initialize}, + userMainMenuChoice{MainMenuSelection::Games}, + userGameChoice{GameSelection::Recall} + { + } bool displayShouldUpdate = true; bool displayIsVisible = true; @@ -85,6 +95,7 @@ namespace Engine Scenes::Canvas::SceneState &getCanvasSceneState() { return canvasSceneState; } private: + SystemCore::ContextManager *contextManager; SystemState systemState; MainMenuSelection userMainMenuChoice; diff --git a/include/games/phase-evasion/state.h b/include/games/phase-evasion/state.h index 19a6499..356264b 100644 --- a/include/games/phase-evasion/state.h +++ b/include/games/phase-evasion/state.h @@ -2,6 +2,11 @@ #include +namespace SystemCore +{ + class ContextManager; +} + namespace Games::PhaseEvasion { enum class Actions @@ -16,17 +21,18 @@ namespace Games::PhaseEvasion class GameState { public: - GameState() : highScore{0}, flaresEvaded{0}, gemsCaptured{0} {} + GameState(SystemCore::ContextManager *ctx) : contextManager{ctx}, highScore{0}, flaresEvaded{0}, gemsCaptured{0} {} uint16_t flaresEvaded; uint16_t gemsCaptured; uint16_t highScore; Actions current = Actions::Startup; + static constexpr const char *memoryKeyName = "phase-high"; + + void reset(); + uint16_t calculateTotalScore() const; + void updateHighScore(uint16_t score); - void reset() - { - highScore = flaresEvaded = gemsCaptured = 0; - // highScore = contextManager->memory.getUInt("phase-evasion-high-score"); - } - uint16_t calculateTotalScore() const { return flaresEvaded + (2 * gemsCaptured); } + private: + SystemCore::ContextManager *contextManager; }; } \ No newline at end of file diff --git a/src/core/context-manager.cpp b/src/core/context-manager.cpp index 17577c5..983f5b1 100644 --- a/src/core/context-manager.cpp +++ b/src/core/context-manager.cpp @@ -7,7 +7,7 @@ namespace SystemCore { - ContextManager::ContextManager() : display{this}, menuNav{this} {} + ContextManager::ContextManager() : display{this}, stateManager{this}, menuNav{this} {} ContextManager::~ContextManager() { diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index e34b6df..d6af5bb 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -113,7 +113,7 @@ namespace Engine #ifdef RELEASE contextManager.memory.begin("lumenlab", false); #else - contextManager.memory.begin("lumenlab-development", false); + contextManager.memory.begin("lumenlab-dev", false); #endif randomSeed(esp_random()); diff --git a/src/engine/state-manager.cpp b/src/engine/state-manager.cpp index bdd2206..645dd32 100644 --- a/src/engine/state-manager.cpp +++ b/src/engine/state-manager.cpp @@ -1,4 +1,5 @@ #include "engine/state-manager.h" +#include "core/context-manager.h" namespace Engine { diff --git a/src/games/phase-evasion/driver.cpp b/src/games/phase-evasion/driver.cpp index a8ca804..772d677 100644 --- a/src/games/phase-evasion/driver.cpp +++ b/src/games/phase-evasion/driver.cpp @@ -205,9 +205,8 @@ namespace Games::PhaseEvasion if (currentScore > highScore) { - contextManager->stateManager.getPhaseEvasionGameState().highScore = currentScore; + contextManager->stateManager.getPhaseEvasionGameState().updateHighScore(currentScore); contextManager->stateManager.displayShouldUpdate = true; - // contextManager->memory.putUInt("phase-evasion-high-score", contextManager->stateManager.getPhaseEvasionGameState().highScore); } } diff --git a/src/games/phase-evasion/flare-manager.cpp b/src/games/phase-evasion/flare-manager.cpp index 5b04f2a..6aca3a9 100644 --- a/src/games/phase-evasion/flare-manager.cpp +++ b/src/games/phase-evasion/flare-manager.cpp @@ -13,6 +13,7 @@ namespace Games::PhaseEvasion { uint16_t colorIndex = static_cast(esp_random()) % arraySize(Lights::colorPalette); flare->activate(Lights::colorPalette[colorIndex], speed); + logf("Flare dispatched: %u", colorIndex); return; } ++flare; diff --git a/src/games/phase-evasion/state.cpp b/src/games/phase-evasion/state.cpp new file mode 100644 index 0000000..067fc5b --- /dev/null +++ b/src/games/phase-evasion/state.cpp @@ -0,0 +1,24 @@ +#include "games/phase-evasion/state.h" +#include "core/context-manager.h" +#include "logger.h" + +namespace Games::PhaseEvasion +{ + void GameState::reset() + { + flaresEvaded = gemsCaptured = 0; + highScore = contextManager->memory.getUInt(memoryKeyName); + } + + uint16_t GameState::calculateTotalScore() const + { + return flaresEvaded + (2 * gemsCaptured); + } + + void GameState::updateHighScore(uint16_t score) + { + highScore = score; + contextManager->memory.putUInt(memoryKeyName, highScore); + logf("High score updated: %u", highScore); + } +} \ No newline at end of file From 348deaacf18d558b99c9a34d8a92648a30e03ca1 Mon Sep 17 00:00:00 2001 From: Eric McDaniel Date: Tue, 10 Feb 2026 23:22:15 -0600 Subject: [PATCH 4/9] Manage menu tile brightness --- src/display/menu-navigation.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/display/menu-navigation.cpp b/src/display/menu-navigation.cpp index ebdc564..03031fa 100644 --- a/src/display/menu-navigation.cpp +++ b/src/display/menu-navigation.cpp @@ -11,7 +11,7 @@ namespace Display Engine::SystemState currentState = contextManager->stateManager.current(); uint16_t displayIndex = SystemCore::Configuration::numLeds - 1; - float inactiveSelectionDimmingScale = currentState == Engine::SystemState::MenuHome ? 1.0f : 0.3f; + float inactiveSelectionDimmingScale = currentState == Engine::SystemState::MenuHome ? 1.0f : 0.6f; constexpr float center = (menuTileWidth - 1) / 2.0f; constexpr double sigma = 3.0f; @@ -20,7 +20,7 @@ namespace Display for (uint16_t i = 0; i < menuTileWidth; ++i) { float x = i - center; - float blend = std::exp(-(x * x) / (2 * sigma * sigma)); // computed gaussian curve + float blend = std::exp(-(x * x) / (4 * sigma * sigma)); // computed gaussian curve if (modeIdx == static_cast(modeSelected)) contextManager->leds.buffer[displayIndex] = Lights::Color{Lights::ColorCode::ThemeGreen} * inactiveSelectionDimmingScale * blend; @@ -41,7 +41,7 @@ namespace Display uint8_t sceneSelected = static_cast(contextManager->stateManager.getUserSceneChoice()); displayIndex = 0; - inactiveSelectionDimmingScale = (currentState == Engine::SystemState::MenuGames || currentState == Engine::SystemState::MenuScenes) ? 1.0f : 0.3f; + inactiveSelectionDimmingScale = (currentState == Engine::SystemState::MenuGames || currentState == Engine::SystemState::MenuScenes) ? 1.0f : 0.6f; uint8_t gamesOrScenesAvailable = modeSelected == Engine::MainMenuSelection::Games ? numGames : numScenes; for (uint8_t modeIdx = 0; modeIdx < gamesOrScenesAvailable; ++modeIdx) @@ -49,7 +49,7 @@ namespace Display for (size_t i = 0; i < menuTileWidth; ++i) { float x = i - center; - float blend = std::exp(-(x * x) / (2 * sigma * sigma)); + float blend = std::exp(-(x * x) / (4 * sigma * sigma)); if (currentState == Engine::SystemState::MenuGames && modeIdx == gameSelected) contextManager->leds.buffer[displayIndex] = Lights::Color{Lights::ColorCode::ThemeBlue} * blend; From 29742d925463813e9e013d202135f6f0a6dc2e11 Mon Sep 17 00:00:00 2001 From: Eric McDaniel Date: Tue, 10 Feb 2026 23:34:02 -0600 Subject: [PATCH 5/9] Set high score Recall logic --- include/engine/state-manager.h | 1 + include/games/recall/state.h | 14 ++++++++++++-- src/games/recall/state.cpp | 20 ++++++++++++++++++++ 3 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 src/games/recall/state.cpp diff --git a/include/engine/state-manager.h b/include/engine/state-manager.h index c55c1a2..192846c 100644 --- a/include/engine/state-manager.h +++ b/include/engine/state-manager.h @@ -59,6 +59,7 @@ namespace Engine public: StateManager(SystemCore::ContextManager *ctx) : contextManager{ctx}, phaseEvasionGameState{ctx}, + recallGameState{ctx}, systemState{SystemState::Initialize}, userMainMenuChoice{MainMenuSelection::Games}, userGameChoice{GameSelection::Recall} diff --git a/include/games/recall/state.h b/include/games/recall/state.h index 8155674..2528521 100644 --- a/include/games/recall/state.h +++ b/include/games/recall/state.h @@ -2,6 +2,11 @@ #include +namespace SystemCore +{ + class ContextManager; +} + namespace Games::Recall { enum class Actions @@ -17,11 +22,16 @@ namespace Games::Recall class GameState { public: - GameState() : highScore{0}, round{0} {} + GameState(SystemCore::ContextManager *ctx) : contextManager{ctx}, highScore{0}, round{0} {} uint16_t highScore; uint16_t round; Actions current = Actions::Startup; + static constexpr const char *memoryKeyName = "recall-high"; + + void reset(); + void updateHighScore(uint16_t score); - void reset() { highScore = round = 0; } + private: + SystemCore::ContextManager *contextManager; }; } \ No newline at end of file diff --git a/src/games/recall/state.cpp b/src/games/recall/state.cpp new file mode 100644 index 0000000..5514887 --- /dev/null +++ b/src/games/recall/state.cpp @@ -0,0 +1,20 @@ +#include "games/phase-evasion/state.h" +#include "core/context-manager.h" +#include "logger.h" + +namespace Games::Recall +{ + + void GameState::reset() + { + round = 0; + highScore = contextManager->memory.getUInt(memoryKeyName); + } + + void GameState::updateHighScore(uint16_t score) + { + highScore = score; + contextManager->memory.putUInt(memoryKeyName, highScore); + logf("High score updated: %u", highScore); + } +} \ No newline at end of file From 7833efcdd1d6400e94462bf72d2ad6b0f262a662 Mon Sep 17 00:00:00 2001 From: Eric McDaniel Date: Tue, 10 Feb 2026 23:43:04 -0600 Subject: [PATCH 6/9] Control when to write high score --- include/games/phase-evasion/state.h | 2 +- include/games/recall/state.h | 2 +- src/games/phase-evasion/driver.cpp | 4 ++-- src/games/phase-evasion/state.cpp | 4 ++-- src/games/recall/driver.cpp | 4 ++++ src/games/recall/state.cpp | 4 ++-- 6 files changed, 12 insertions(+), 8 deletions(-) diff --git a/include/games/phase-evasion/state.h b/include/games/phase-evasion/state.h index 356264b..409b319 100644 --- a/include/games/phase-evasion/state.h +++ b/include/games/phase-evasion/state.h @@ -30,7 +30,7 @@ namespace Games::PhaseEvasion void reset(); uint16_t calculateTotalScore() const; - void updateHighScore(uint16_t score); + void updateHighScore(); private: SystemCore::ContextManager *contextManager; diff --git a/include/games/recall/state.h b/include/games/recall/state.h index 2528521..cdcdeab 100644 --- a/include/games/recall/state.h +++ b/include/games/recall/state.h @@ -29,7 +29,7 @@ namespace Games::Recall static constexpr const char *memoryKeyName = "recall-high"; void reset(); - void updateHighScore(uint16_t score); + void updateHighScore(); private: SystemCore::ContextManager *contextManager; diff --git a/src/games/phase-evasion/driver.cpp b/src/games/phase-evasion/driver.cpp index 772d677..7c8d231 100644 --- a/src/games/phase-evasion/driver.cpp +++ b/src/games/phase-evasion/driver.cpp @@ -198,14 +198,14 @@ namespace Games::PhaseEvasion void Driver::checkIfHighScore() { - const GameState state = contextManager->stateManager.getPhaseEvasionGameState(); + GameState state = contextManager->stateManager.getPhaseEvasionGameState(); const uint16_t highScore = state.highScore; const uint16_t currentScore = state.calculateTotalScore(); if (currentScore > highScore) { - contextManager->stateManager.getPhaseEvasionGameState().updateHighScore(currentScore); + state.updateHighScore(); contextManager->stateManager.displayShouldUpdate = true; } } diff --git a/src/games/phase-evasion/state.cpp b/src/games/phase-evasion/state.cpp index 067fc5b..47a197f 100644 --- a/src/games/phase-evasion/state.cpp +++ b/src/games/phase-evasion/state.cpp @@ -15,9 +15,9 @@ namespace Games::PhaseEvasion return flaresEvaded + (2 * gemsCaptured); } - void GameState::updateHighScore(uint16_t score) + void GameState::updateHighScore() { - highScore = score; + highScore = calculateTotalScore(); contextManager->memory.putUInt(memoryKeyName, highScore); logf("High score updated: %u", highScore); } diff --git a/src/games/recall/driver.cpp b/src/games/recall/driver.cpp index b6ac0ab..d7e15c8 100644 --- a/src/games/recall/driver.cpp +++ b/src/games/recall/driver.cpp @@ -131,6 +131,10 @@ namespace Games::Recall { state.current = Actions::PlayerResponseVerified; ++state.round; + if (state.round > state.highScore) + { + state.updateHighScore(); + } contextManager->stateManager.displayShouldUpdate = true; contextManager->controller.reset(); wait(gameplaySpeedIlluminated * 2); diff --git a/src/games/recall/state.cpp b/src/games/recall/state.cpp index 5514887..0709edb 100644 --- a/src/games/recall/state.cpp +++ b/src/games/recall/state.cpp @@ -11,9 +11,9 @@ namespace Games::Recall highScore = contextManager->memory.getUInt(memoryKeyName); } - void GameState::updateHighScore(uint16_t score) + void GameState::updateHighScore() { - highScore = score; + highScore = round; contextManager->memory.putUInt(memoryKeyName, highScore); logf("High score updated: %u", highScore); } From 536f91a23b9dba8874942df0f2efd66604cf1592 Mon Sep 17 00:00:00 2001 From: Eric McDaniel Date: Tue, 10 Feb 2026 23:52:54 -0600 Subject: [PATCH 7/9] Display high score on OLED screen --- src/display/display.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/display/display.cpp b/src/display/display.cpp index 491de47..caa508a 100644 --- a/src/display/display.cpp +++ b/src/display/display.cpp @@ -171,24 +171,28 @@ namespace Display void OledDisplay::drawRecallGameHud() { + const auto recallState = contextManager->stateManager.getRecallGameState(); + const auto round = recallState.round; + const auto highScore = recallState.highScore; + display.clearDisplay(); drawHeader("Recall"); display.setCursor(0, 16); - display.print("Round: "); - display.print(contextManager->stateManager.getRecallGameState().round + 1); + display.printf("Round: %u", round + 1); display.setCursor(0, 24); - display.print("High Score: -"); + display.printf("High Score: %u", highScore + 1); display.display(); } void OledDisplay::drawPhaseEvasionGameHud() { - const auto flaresEvaded = contextManager->stateManager.getPhaseEvasionGameState().flaresEvaded; - const auto gemsCaptured = contextManager->stateManager.getPhaseEvasionGameState().gemsCaptured; - const auto totalScore = contextManager->stateManager.getPhaseEvasionGameState().calculateTotalScore(); - const auto highScore = contextManager->stateManager.getPhaseEvasionGameState().highScore; + const auto phaseEvasionState = contextManager->stateManager.getPhaseEvasionGameState(); + const auto flaresEvaded = phaseEvasionState.flaresEvaded; + const auto gemsCaptured = phaseEvasionState.gemsCaptured; + const auto totalScore = phaseEvasionState.calculateTotalScore(); + const auto highScore = phaseEvasionState.highScore; display.clearDisplay(); drawHeader("Phase Evasion"); From 76017ada4293a6b517d52e5b0a7acc909da453cb Mon Sep 17 00:00:00 2001 From: Eric McDaniel Date: Wed, 11 Feb 2026 00:52:22 -0600 Subject: [PATCH 8/9] Refactor high score calc ownership --- include/games/phase-evasion/state.h | 1 + include/games/recall/state.h | 3 ++- src/games/phase-evasion/driver.cpp | 10 +--------- src/games/phase-evasion/state.cpp | 9 +++++++++ src/games/recall/driver.cpp | 9 +++------ src/games/recall/state.cpp | 16 ++++++++++++++++ 6 files changed, 32 insertions(+), 16 deletions(-) diff --git a/include/games/phase-evasion/state.h b/include/games/phase-evasion/state.h index 409b319..522e581 100644 --- a/include/games/phase-evasion/state.h +++ b/include/games/phase-evasion/state.h @@ -30,6 +30,7 @@ namespace Games::PhaseEvasion void reset(); uint16_t calculateTotalScore() const; + void checkHighScore(); void updateHighScore(); private: diff --git a/include/games/recall/state.h b/include/games/recall/state.h index cdcdeab..1cbf4b5 100644 --- a/include/games/recall/state.h +++ b/include/games/recall/state.h @@ -22,13 +22,14 @@ namespace Games::Recall class GameState { public: - GameState(SystemCore::ContextManager *ctx) : contextManager{ctx}, highScore{0}, round{0} {} + GameState(SystemCore::ContextManager *ctx); uint16_t highScore; uint16_t round; Actions current = Actions::Startup; static constexpr const char *memoryKeyName = "recall-high"; void reset(); + void incrementScore(); void updateHighScore(); private: diff --git a/src/games/phase-evasion/driver.cpp b/src/games/phase-evasion/driver.cpp index 7c8d231..94e6a80 100644 --- a/src/games/phase-evasion/driver.cpp +++ b/src/games/phase-evasion/driver.cpp @@ -199,15 +199,7 @@ namespace Games::PhaseEvasion void Driver::checkIfHighScore() { GameState state = contextManager->stateManager.getPhaseEvasionGameState(); - - const uint16_t highScore = state.highScore; - const uint16_t currentScore = state.calculateTotalScore(); - - if (currentScore > highScore) - { - state.updateHighScore(); - contextManager->stateManager.displayShouldUpdate = true; - } + state.checkHighScore(); } void Driver::muzzleFlash() diff --git a/src/games/phase-evasion/state.cpp b/src/games/phase-evasion/state.cpp index 47a197f..4862784 100644 --- a/src/games/phase-evasion/state.cpp +++ b/src/games/phase-evasion/state.cpp @@ -15,6 +15,15 @@ namespace Games::PhaseEvasion return flaresEvaded + (2 * gemsCaptured); } + void GameState::checkHighScore() + { + if (calculateTotalScore() > highScore) + { + updateHighScore(); + contextManager->stateManager.displayShouldUpdate = true; + } + } + void GameState::updateHighScore() { highScore = calculateTotalScore(); diff --git a/src/games/recall/driver.cpp b/src/games/recall/driver.cpp index d7e15c8..3758e59 100644 --- a/src/games/recall/driver.cpp +++ b/src/games/recall/driver.cpp @@ -40,6 +40,7 @@ namespace Games::Recall if (isReady()) { state.current = Actions::ComputerPlaybackOnDisplay; + state.reset(); wait(gameplaySpeedIlluminated); } break; @@ -130,12 +131,8 @@ namespace Games::Recall if (sequenceIndex > state.round && isReady()) { state.current = Actions::PlayerResponseVerified; - ++state.round; - if (state.round > state.highScore) - { - state.updateHighScore(); - } - contextManager->stateManager.displayShouldUpdate = true; + state.incrementScore(); + contextManager->controller.reset(); wait(gameplaySpeedIlluminated * 2); return; diff --git a/src/games/recall/state.cpp b/src/games/recall/state.cpp index 0709edb..4506e43 100644 --- a/src/games/recall/state.cpp +++ b/src/games/recall/state.cpp @@ -5,10 +5,16 @@ namespace Games::Recall { + GameState::GameState(SystemCore::ContextManager *ctx) : contextManager{ctx} + { + reset(); + } + void GameState::reset() { round = 0; highScore = contextManager->memory.getUInt(memoryKeyName); + contextManager->stateManager.displayShouldUpdate = true; } void GameState::updateHighScore() @@ -17,4 +23,14 @@ namespace Games::Recall contextManager->memory.putUInt(memoryKeyName, highScore); logf("High score updated: %u", highScore); } + + void GameState::incrementScore() + { + ++round; + if (round > highScore) + { + updateHighScore(); + } + contextManager->stateManager.displayShouldUpdate = true; + } } \ No newline at end of file From 3dafb7a5b39eac3cb4f942a45c40e3678b26f28f Mon Sep 17 00:00:00 2001 From: Eric McDaniel Date: Wed, 11 Feb 2026 01:09:10 -0600 Subject: [PATCH 9/9] Ensure score resets on game change, bump to C++20 --- include/games/phase-evasion/driver.h | 1 + include/games/recall/driver.h | 1 + platformio.ini | 8 ++++---- src/games/phase-evasion/driver.cpp | 6 ++++-- src/games/recall/driver.cpp | 2 ++ 5 files changed, 12 insertions(+), 6 deletions(-) diff --git a/include/games/phase-evasion/driver.h b/include/games/phase-evasion/driver.h index ada133f..0a3f181 100644 --- a/include/games/phase-evasion/driver.h +++ b/include/games/phase-evasion/driver.h @@ -14,6 +14,7 @@ namespace Games::PhaseEvasion { public: Driver(SystemCore::ContextManager *ctx); + ~Driver() { state.reset(); } void nextEvent() override; static constexpr uint16_t playerOffset = 25; static constexpr uint16_t playerWidth = 5; diff --git a/include/games/recall/driver.h b/include/games/recall/driver.h index 9f2a75e..bdf4509 100644 --- a/include/games/recall/driver.h +++ b/include/games/recall/driver.h @@ -13,6 +13,7 @@ namespace Games::Recall { public: Driver(SystemCore::ContextManager *ctx); + ~Driver() { state.reset(); } void nextEvent() override; private: diff --git a/platformio.ini b/platformio.ini index d121867..6bf75eb 100644 --- a/platformio.ini +++ b/platformio.ini @@ -26,7 +26,7 @@ framework = arduino build_type = debug build_unflags = -std=gnu++11 -build_flags = -g -DVIRTUALIZATION -std=gnu++17 +build_flags = -g -DVIRTUALIZATION -std=gnu++2a [env:debug] platform = espressif32 @@ -34,7 +34,7 @@ board = upesy_wroom framework = arduino build_type = debug build_unflags = -std=gnu++11 -build_flags = -g -DDEBUG -std=gnu++17 +build_flags = -g -DDEBUG -std=gnu++2a [env:release] platform = espressif32 @@ -43,7 +43,7 @@ framework = arduino lib_ignore = debug-fastled build_type = release build_unflags = -std=gnu++11 -build_flags = -Os -DRELEASE -std=gnu++17 +build_flags = -Os -DRELEASE -std=gnu++2a [env:native] platform = native @@ -53,4 +53,4 @@ build_flags = -I.pio/libdeps/native/googletest/googletest/include/gtest -I.pio/libdeps/native/googletest/googlemock/include/gmock -pthread - -std=gnu++17 + -std=gnu++2a diff --git a/src/games/phase-evasion/driver.cpp b/src/games/phase-evasion/driver.cpp index 94e6a80..71e9d68 100644 --- a/src/games/phase-evasion/driver.cpp +++ b/src/games/phase-evasion/driver.cpp @@ -26,6 +26,7 @@ namespace Games::PhaseEvasion if (isReady()) { state.current = Actions::ActiveGame; + state.reset(); log("Starting new game."); } break; @@ -235,8 +236,6 @@ namespace Games::PhaseEvasion if (contextManager->controller.wasPressed(::Player::ControllerButton::Start)) { - state.current = Actions::Startup; - state.reset(); contextManager->stateManager.displayShouldUpdate = true; reset(); windDownTimer.wait(windDownLength); @@ -252,6 +251,9 @@ namespace Games::PhaseEvasion gem.wait(gemRespawnDelay); flareManager.reset(); player.setPosition(static_cast(0)); + state.current = Actions::Startup; + state.reset(); + contextManager->stateManager.displayShouldUpdate = true; wait(500); } } \ No newline at end of file diff --git a/src/games/recall/driver.cpp b/src/games/recall/driver.cpp index 3758e59..e39b3cd 100644 --- a/src/games/recall/driver.cpp +++ b/src/games/recall/driver.cpp @@ -12,6 +12,7 @@ namespace Games::Recall state = contextManager->stateManager.getRecallGameState(); state.reset(); state.current = Actions::Startup; + contextManager->stateManager.displayShouldUpdate = true; wait(gameplaySpeedIlluminated); } @@ -41,6 +42,7 @@ namespace Games::Recall { state.current = Actions::ComputerPlaybackOnDisplay; state.reset(); + contextManager->stateManager.displayShouldUpdate = true; wait(gameplaySpeedIlluminated); } break;