From 2e8007d510f6d8a4d3ff85e9cb4580101ad7d3b4 Mon Sep 17 00:00:00 2001 From: Mark van Renswoude Date: Mon, 5 Dec 2016 23:42:20 +0100 Subject: [PATCH] Support for gun armed detection First attempt at implementing animation --- Button.cpp | 2 +- Globals.cpp | 1 + Globals.h | 1 + NerfStatTrek.ino | 8 + SegmentDisplay.cpp | 34 ++- SegmentDisplay.h | 6 +- SegmentDisplayChars.h | 580 +++++++++++++++++++++--------------------- StateDefault.cpp | 4 +- StateDefault.h | 4 +- StateLoseTheGame.cpp | 72 +++++- StateLoseTheGame.h | 8 + StateUserUnknown.cpp | 50 +++- StateUserUnknown.h | 5 + 13 files changed, 469 insertions(+), 306 deletions(-) diff --git a/Button.cpp b/Button.cpp index 7fc5426..59b9e79 100644 --- a/Button.cpp +++ b/Button.cpp @@ -7,7 +7,7 @@ void Button::init(uint8_t pin, int offState, bool usePullUp) this->offState = offState; this->lastState = offState; - if (offState == HIGH && usePullUp) + if (usePullUp) pinMode(pin, INPUT_PULLUP); else pinMode(pin, INPUT); diff --git a/Globals.cpp b/Globals.cpp index 0f833a0..9019ba7 100644 --- a/Globals.cpp +++ b/Globals.cpp @@ -5,6 +5,7 @@ SegmentDisplay* display; Button* buttonA; Button* buttonB; +Button* buttonArmed; uint32_t shots = 0; uint32_t hits = 0; diff --git a/Globals.h b/Globals.h index 65c15f8..a695589 100644 --- a/Globals.h +++ b/Globals.h @@ -9,6 +9,7 @@ extern SegmentDisplay* display; extern Button* buttonA; extern Button* buttonB; +extern Button* buttonArmed; extern uint32_t shots; extern uint32_t hits; diff --git a/NerfStatTrek.ino b/NerfStatTrek.ino index 055086c..e19cf58 100644 --- a/NerfStatTrek.ino +++ b/NerfStatTrek.ino @@ -29,6 +29,9 @@ void setup() buttonB = new Button(); buttonB->init(NerfButtonB); + buttonArmed = new Button(); + buttonArmed->init(NerfButtonArmed, LOW); + setCurrentState(new DefaultState()); } @@ -40,6 +43,11 @@ void loop() buttonA->update(currentTime); buttonB->update(currentTime); + buttonArmed->update(currentTime); + + // Count the shot no matter which state we're in + if (buttonArmed->changed() && !buttonArmed->pressed()) + shots++; currentState->loop(); } diff --git a/SegmentDisplay.cpp b/SegmentDisplay.cpp index f3d5dfb..14c0e23 100644 --- a/SegmentDisplay.cpp +++ b/SegmentDisplay.cpp @@ -39,6 +39,12 @@ void SegmentDisplay::end() } +void SegmentDisplay::clear() +{ + writeDisplay(0, 0); +} + + void SegmentDisplay::writeNumber(uint32_t value) { #if defined(SDSerialDebug) @@ -58,7 +64,7 @@ void SegmentDisplay::writeNumber(uint32_t value) } -void SegmentDisplay::writeTextLeft(char* value) +void SegmentDisplay::writeTextLeft(char const* value) { #if defined(SDSerialDebug) Serial.print("SegmentDisplay::writeTextLeft: " + value + "\n"); @@ -84,15 +90,29 @@ void SegmentDisplay::writeTextLeft(char* value) } -void SegmentDisplay::writeTextCenter(char* value) +void SegmentDisplay::writeRaw(char const* value) { - // TODO -} + #if defined(SDSerialDebug) + Serial.print("SegmentDisplay::writeRaw: " + value + "\n"); + #endif + byte digitMask = 1 << (digits - 1); + byte charIndex = 0; -void SegmentDisplay::writeTextRight(char* value) -{ - // TODO + while (charIndex < digits && value[charIndex] != '\0') + { + writeDisplay(value[charIndex], digitMask); + + digitMask >>= 1; + charIndex++; + } + + while (charIndex < digits) + { + writeDisplay(0, digitMask); + digitMask >>= 1; + charIndex++; + } } diff --git a/SegmentDisplay.h b/SegmentDisplay.h index d1453e4..5182409 100644 --- a/SegmentDisplay.h +++ b/SegmentDisplay.h @@ -28,10 +28,10 @@ class SegmentDisplay void begin(); void end(); + void clear(); void writeNumber(uint32_t value); - void writeTextLeft(char* value); - void writeTextCenter(char* value); - void writeTextRight(char* value); + void writeTextLeft(char const* value); + void writeRaw(char const* value); byte getDigits() { return digits; } void setDigits(byte value) { digits = value; } diff --git a/SegmentDisplayChars.h b/SegmentDisplayChars.h index 1a764a3..407a63d 100644 --- a/SegmentDisplayChars.h +++ b/SegmentDisplayChars.h @@ -11,6 +11,7 @@ #define SegmentE 16 // Bottom left #define SegmentF 32 // Top left #define SegmentG 64 // Middle +#define SegmentDP (char)128 // Dot point #define ASCIIZero 48 @@ -21,300 +22,305 @@ #define ASCIILowercaseZ 122 +/** + * _ + * | | + * |_| + * +**/ +#define Char0 SegmentA | SegmentB | SegmentC | SegmentD | SegmentE | SegmentF + +/** + * + * | + * | + * +**/ +#define Char1 SegmentB | SegmentC + +/** + * _ + * _| + * |_ + * +**/ +#define Char2 SegmentA | SegmentB | SegmentD | SegmentE | SegmentG + +/** + * _ + * _| + * _| + * +**/ +#define Char3 SegmentA | SegmentB | SegmentC | SegmentD | SegmentG + +/** + * + * |_| + * | + * +**/ +#define Char4 SegmentB | SegmentC | SegmentF | SegmentG + +/** + * _ + * |_ + * _| + * +**/ +#define Char5 SegmentA | SegmentC | SegmentD | SegmentF | SegmentG + +/** + * _ + * |_ + * |_| + * +**/ +#define Char6 SegmentA | SegmentC | SegmentD | SegmentE | SegmentF | SegmentG + +/** + * _ + * | + * | + * +**/ +#define Char7 SegmentA | SegmentB | SegmentC + +/** + * _ + * |_| + * |_| + * +**/ +#define Char8 SegmentA | SegmentB | SegmentC | SegmentD | SegmentE | SegmentF | SegmentG + +/** + * _ + * |_| + * _| + * +**/ +#define Char9 SegmentA | SegmentB | SegmentC | SegmentD | SegmentF | SegmentG + + +/** + * _ + * |_| + * | | + * +**/ +#define CharA SegmentA | SegmentB | SegmentC | SegmentE | SegmentF | SegmentG + +/** + * + * |_ + * |_| + * +**/ +#define CharB SegmentC | SegmentD | SegmentE | SegmentF | SegmentG + +/** + * _ + * | + * |_ + * +**/ +#define CharC SegmentA | SegmentD | SegmentE | SegmentF + +/** + * + * _| + * |_| + * +**/ +#define CharD SegmentB | SegmentC | SegmentD | SegmentE | SegmentG + +/** + * _ + * |_ + * |_ + * +**/ +#define CharE SegmentA | SegmentD | SegmentE | SegmentF | SegmentG + +/** + * _ + * |_ + * | + * +**/ +#define CharF SegmentA | SegmentE | SegmentF | SegmentG + +/** + * _ + * |_| + * _| + * +**/ +#define CharG SegmentA | SegmentB | SegmentC | SegmentD | SegmentF | SegmentG + +/** + * + * |_| + * | | + * +**/ +#define CharH SegmentB | SegmentC | SegmentE | SegmentF | SegmentG + +/** + * + * | + * | + * +**/ +#define CharI SegmentE | SegmentF + +/** + * + * | + * |_| + * +**/ +#define CharJ SegmentB | SegmentC | SegmentD | SegmentE + +/** + * + * |_ + * | + * +**/ +#define CharK SegmentE | SegmentF | SegmentG + +/** + * + * | + * |_ + * +**/ +#define CharL SegmentD | SegmentE | SegmentF + +/** + * _ + * + * | | + * +**/ +#define CharM SegmentA | SegmentC | SegmentE + +/** + * + * _ + * | | + * +**/ +#define CharN SegmentC | SegmentE | SegmentG + +/** + * _ + * | | + * |_| + * +**/ +#define CharO SegmentA | SegmentB | SegmentC | SegmentD | SegmentE | SegmentF + +/** + * _ + * |_| + * | + * +**/ +#define CharP SegmentA | SegmentB | SegmentE | SegmentF | SegmentG + +/** + * _ + * |_| + * | + * +**/ +#define CharQ SegmentA | SegmentB | SegmentC | SegmentF | SegmentG + +/** + * + * _ + * | + * +**/ +#define CharR SegmentE | SegmentG + +/** + * _ + * |_ + * _| + * +**/ +#define CharS SegmentA | SegmentC | SegmentD | SegmentF | SegmentG + +/** + * + * |_ + * |_ + * +**/ +#define CharT SegmentD | SegmentE | SegmentF | SegmentG + +/** + * + * | | + * |_| + * +**/ +#define CharU SegmentB | SegmentC | SegmentD | SegmentE | SegmentF + +/** + * + * + * |_| + * +**/ +#define CharV SegmentC | SegmentD | SegmentE + +/** + * + * | | + * _ + * +**/ +#define CharW SegmentB | SegmentD | SegmentF + +/** + * + * _| + * | + * +**/ +#define CharX SegmentB | SegmentC | SegmentG + +/** + * + * |_| + * _| + * +**/ +#define CharY SegmentB | SegmentC | SegmentD | SegmentF | SegmentG + +/** + * _ + * _| + * |_ + * +**/ +#define CharZ SegmentA | SegmentB | SegmentD | SegmentE | SegmentG + const byte SDNumberSegments[10] PROGMEM = { - /** - * _ - * | | - * |_| - * - **/ - SegmentA | SegmentB | SegmentC | SegmentD | SegmentE | SegmentF, - - /** - * - * | - * | - * - **/ - SegmentB | SegmentC, - - /** - * _ - * _| - * |_ - * - **/ - SegmentA | SegmentB | SegmentD | SegmentE | SegmentG, - - /** - * _ - * _| - * _| - * - **/ - SegmentA | SegmentB | SegmentC | SegmentD | SegmentG, - - /** - * - * |_| - * | - * - **/ - SegmentB | SegmentC | SegmentF | SegmentG, - - /** - * _ - * |_ - * _| - * - **/ - SegmentA | SegmentC | SegmentD | SegmentF | SegmentG, - - /** - * _ - * |_ - * |_| - * - **/ - SegmentA | SegmentC | SegmentD | SegmentE | SegmentF | SegmentG, - - /** - * _ - * | - * | - * - **/ - SegmentA | SegmentB | SegmentC, - - /** - * _ - * |_| - * |_| - * - **/ - SegmentA | SegmentB | SegmentC | SegmentD | SegmentE | SegmentF | SegmentG, - - /** - * _ - * |_| - * _| - * - **/ - SegmentA | SegmentB | SegmentC | SegmentD | SegmentF | SegmentG + Char0, Char1, Char2, Char3, Char4, Char5, Char6, Char7, Char8, Char9 }; - const byte SDCharacterSegments[26] PROGMEM = { - /** - * _ - * |_| - * | | - * - **/ - SegmentA | SegmentB | SegmentC | SegmentE | SegmentF | SegmentG, - - /** - * - * |_ - * |_| - * - **/ - SegmentC | SegmentD | SegmentE | SegmentF | SegmentG, - - /** - * _ - * | - * |_ - * - **/ - SegmentA | SegmentD | SegmentE | SegmentF, - - /** - * - * _| - * |_| - * - **/ - SegmentB | SegmentC | SegmentD | SegmentE | SegmentG, - - /** - * _ - * |_ - * |_ - * - **/ - SegmentA | SegmentD | SegmentE | SegmentF | SegmentG, - - /** - * _ - * |_ - * | - * - **/ - SegmentA | SegmentE | SegmentF | SegmentG, - - /** - * _ - * |_| - * _| - * - **/ - SegmentA | SegmentB | SegmentC | SegmentD | SegmentF | SegmentG, - - /** - * - * |_| - * | | - * - **/ - SegmentB | SegmentC | SegmentE | SegmentF | SegmentG, - - /** - * - * | - * | - * - **/ - SegmentE | SegmentF, - - /** - * - * | - * |_| - * - **/ - SegmentB | SegmentC | SegmentD | SegmentE, - - /** - * - * |_ - * | - * - **/ - SegmentE | SegmentF | SegmentG, - - /** - * - * | - * |_ - * - **/ - SegmentD | SegmentE | SegmentF, - - /** - * _ - * - * | | - * - **/ - SegmentA | SegmentC | SegmentE, - - /** - * - * _ - * | | - * - **/ - SegmentC | SegmentE | SegmentG, - - /** - * _ - * | | - * |_| - * - **/ - SegmentA | SegmentB | SegmentC | SegmentD | SegmentE | SegmentF, - - /** - * _ - * |_| - * | - * - **/ - SegmentA | SegmentB | SegmentE | SegmentF | SegmentG, - - /** - * _ - * |_| - * | - * - **/ - SegmentA | SegmentB | SegmentC | SegmentF | SegmentG, - - /** - * - * _ - * | - * - **/ - SegmentE | SegmentG, - - /** - * _ - * |_ - * _| - * - **/ - SegmentA | SegmentC | SegmentD | SegmentF | SegmentG, - - /** - * - * |_ - * |_ - * - **/ - SegmentD | SegmentE | SegmentF | SegmentG, - - /** - * - * | | - * |_| - * - **/ - SegmentB | SegmentC | SegmentD | SegmentE | SegmentF, - - /** - * - * - * |_| - * - **/ - SegmentC | SegmentD | SegmentE, - - /** - * - * | | - * _ - * - **/ - SegmentB | SegmentD | SegmentF, - - /** - * - * _| - * | - * - **/ - SegmentB | SegmentC | SegmentG, - - /** - * - * |_| - * _| - * - **/ - SegmentB | SegmentC | SegmentD | SegmentF | SegmentG, - - /** - * _ - * _| - * |_ - * - **/ - SegmentA | SegmentB | SegmentD | SegmentE | SegmentG + CharA, CharB, CharC, CharD, CharE, CharF, CharG, CharH, CharI, CharJ, CharK, CharL, CharM, + CharN, CharO, CharP, CharQ, CharR, CharS, CharT, CharU, CharV, CharW, CharX, CharY, CharZ }; #endif diff --git a/StateDefault.cpp b/StateDefault.cpp index b5dbdeb..4a9f6c1 100644 --- a/StateDefault.cpp +++ b/StateDefault.cpp @@ -19,7 +19,7 @@ void DefaultState::loop() if (buttonA->pressed() && buttonB->pressed()) { // A + B - setCurrentState(new LoseTheGameState()); + setCurrentState(new UserUnknownState()); return; } @@ -41,7 +41,7 @@ void DefaultState::loop() // B long if (buttonB->pressed() && buttonB->pressedMillis(currentTime) > NerfButtonLongPressThreshold) { - setCurrentState(new UserUnknownState()); + setCurrentState(new LoseTheGameState()); return; } diff --git a/StateDefault.h b/StateDefault.h index 83cd360..e4afa4f 100644 --- a/StateDefault.h +++ b/StateDefault.h @@ -12,8 +12,8 @@ * * A: Add hit * B short: Toggle between hits and shots and restart state - * B long: Display "Error user unknwn" - * A + B: Display "You lost the game" animation (losethegame.com - you're welcome!) + * A + B: Display "Error user unknwn" + * B long: Display "You lost the game" animation (losethegame.com - you're welcome!) **/ class DefaultState : public AbstractStateHandler { diff --git a/StateLoseTheGame.cpp b/StateLoseTheGame.cpp index 24c72dd..f61a01e 100644 --- a/StateLoseTheGame.cpp +++ b/StateLoseTheGame.cpp @@ -3,8 +3,68 @@ #include "StateDefault.h" +#include "SegmentDisplayChars.h" + +#define CharPipeLeft SegmentE | SegmentF +#define CharPipeRight SegmentB | SegmentC + + +struct Frame +{ + uint32_t time; + char frame[6]; +}; + + +Frame const animation[] = { + // Snake towards the middle + { 100, { SegmentF, 0, 0, 0, 0, SegmentB } }, + { 100, { SegmentF | SegmentE, 0, 0, 0, 0, SegmentB | SegmentC } }, + { 100, { SegmentE | SegmentD, 0, 0, 0, 0, SegmentC | SegmentD } }, + { 100, { SegmentD | SegmentC, 0, 0, 0, 0, SegmentD | SegmentE } }, + { 100, { SegmentC | SegmentB, 0, 0, 0, 0, SegmentE | SegmentF } }, + + { 100, { SegmentB, SegmentF, 0, 0, SegmentB, SegmentF } }, + { 100, { 0, SegmentF | SegmentE, 0, 0, SegmentB | SegmentC, 0 } }, + { 100, { 0, SegmentE | SegmentD, 0, 0, SegmentC | SegmentD, 0 } }, + { 100, { 0, SegmentD | SegmentC, 0, 0, SegmentD | SegmentE, 0 } }, + { 100, { 0, SegmentC | SegmentB, 0, 0, SegmentE | SegmentF, 0 } }, + + { 100, { 0, SegmentB, SegmentF, SegmentB, SegmentF, 0 } }, + { 100, { 0, 0, SegmentF | SegmentE, SegmentB | SegmentC, 0, 0 } }, + { 100, { 0, 0, SegmentE | SegmentD, SegmentC | SegmentD, 0, 0 } }, + { 100, { 0, 0, SegmentD | SegmentC, SegmentD | SegmentE, 0, 0 } }, + { 500, { 0, 0, SegmentC | SegmentB, SegmentE | SegmentF, 0, 0 } }, + + // Slide open to reveal 'you' + { 100, { 0, 0, CharPipeLeft | CharO, CharU | CharPipeRight, 0, 0 } }, + { 100, { 0, CharPipeRight, CharO, CharU, CharPipeLeft, 0 } }, + { 100, { 0, CharPipeLeft | CharY, CharO, CharU, CharPipeRight, 0 } }, + { 100, { CharPipeRight, CharY, CharO, CharU, 0, CharPipeLeft } }, + { 100, { CharPipeLeft, CharY, CharO, CharU, 0, CharPipeRight } }, + { 500, { 0, CharY, CharO, CharU, 0, 0 } }, + + // The rest of the text + { 750, { 0, CharL, CharO, CharS, CharT, 0 } }, + { 750, { 0, 0, CharT, CharH, CharE, 0 } }, + { 500, { SegmentDP, CharG, CharA | SegmentDP, CharM, CharE | SegmentDP, 0 } }, + { 500, { 0, CharG | SegmentDP, CharA, CharM | SegmentDP, CharE, SegmentDP } }, + { 500, { SegmentDP, CharG, CharA | SegmentDP, CharM, CharE | SegmentDP, 0 } }, + { 500, { 0, CharG | SegmentDP, CharA, CharM | SegmentDP, CharE, SegmentDP } }, + { 500, { SegmentDP, CharG, CharA | SegmentDP, CharM, CharE | SegmentDP, 0 } }, + { 500, { 0, CharG | SegmentDP, CharA, CharM | SegmentDP, CharE, SegmentDP } }, + { 500, { SegmentDP, CharG, CharA | SegmentDP, CharM, CharE | SegmentDP, 0 } }, + { 500, { 0, CharG | SegmentDP, CharA, CharM | SegmentDP, CharE, SegmentDP } }, + + { 0, { 0, 0, 0, 0, 0, 0 } } +}; + + + void LoseTheGameState::setup() { + animationTime = currentTime; + animationStep = 0; } void LoseTheGameState::loop() @@ -14,6 +74,14 @@ void LoseTheGameState::loop() setCurrentState(new DefaultState()); } - char text[] = "Lost"; - display->writeTextLeft(text); + if (currentTime - animationTime > animation[animationStep].time) + { + animationStep++; + animationTime = currentTime; + + if (animation[animationStep].time == 0) + setCurrentState(new DefaultState()); + } + + display->writeRaw(animation[animationStep].frame); } \ No newline at end of file diff --git a/StateLoseTheGame.h b/StateLoseTheGame.h index 5aa9c81..a4b1928 100644 --- a/StateLoseTheGame.h +++ b/StateLoseTheGame.h @@ -1,17 +1,25 @@ #ifndef StateLoseTheGame_h #define StateLoseTheGame_h +#include "Arduino.h" #include "StateHandler.h" /** * Lose the game state + * + * Note that the animation in this state is hardcoded + * to 6 digits. **/ class LoseTheGameState : public AbstractStateHandler { public: void setup(); void loop(); + + private: + unsigned long animationTime; + byte animationStep; }; #endif \ No newline at end of file diff --git a/StateUserUnknown.cpp b/StateUserUnknown.cpp index ad2fd49..f809224 100644 --- a/StateUserUnknown.cpp +++ b/StateUserUnknown.cpp @@ -5,6 +5,8 @@ void UserUnknownState::setup() { + animationTime = currentTime; + animationStep = 0; } void UserUnknownState::loop() @@ -14,6 +16,50 @@ void UserUnknownState::loop() setCurrentState(new DefaultState()); } - char text[] = "Unknwn"; - display->writeTextLeft(text); + if (currentTime - animationTime > 500) + { + animationStep++; + animationTime = currentTime; + + if (animationStep == 12) + animationStep = 0; + } + + switch (animationStep) + { + case 0: + case 2: + case 4: + { + char text[] = "ERROR"; + display->writeTextLeft(text); + break; + } + + case 1: + case 3: + case 5: + { + display->clear(); + break; + } + + case 6: + case 7: + case 8: + { + char text[] = "user"; + display->writeTextLeft(text); + break; + } + + case 9: + case 10: + case 11: + { + char text[] = "unknwn"; + display->writeTextLeft(text); + break; + } + } } \ No newline at end of file diff --git a/StateUserUnknown.h b/StateUserUnknown.h index 9bed0f6..2ebcc63 100644 --- a/StateUserUnknown.h +++ b/StateUserUnknown.h @@ -1,6 +1,7 @@ #ifndef StateUserUnknown_h #define StateUserUnknown_h +#include "Arduino.h" #include "StateHandler.h" @@ -14,6 +15,10 @@ class UserUnknownState : public AbstractStateHandler public: void setup(); void loop(); + + private: + unsigned long animationTime; + byte animationStep; }; #endif \ No newline at end of file