Rewrite program layout to state machine

pull/14/head
Dennis Bücker 2 years ago
parent 9eb5512a1a
commit a6ebb233e6
  1. 38
      src/ShowColorSequence.cpp
  2. 68
      src/SimonDisplay.cpp
  3. 53
      src/SimonDisplay.h
  4. 156
      src/SimonSays.cpp
  5. 82
      src/SimonSays.h
  6. 9
      src/main.cpp

@ -0,0 +1,38 @@
#include "SimonSays.h"
ShowColorSequence::ShowColorSequence():
positionDisplay{0},
speed{10},
ticksTillNextColor{100}
{}
void ShowColorSequence::enter(SimonSays & simonSays)
{
positionDisplay = 0;
simonSays.simonDisplay.setActiveColor(simonSays.currentSequence[positionDisplay]);
}
void ShowColorSequence::update(SimonSays & simonSays)
{
if (ticksTillNextColor > 0)
{
--ticksTillNextColor;
}
else
{
simonSays.simonDisplay.setActiveColor(simonSays.currentSequence[positionDisplay]);
Serial.print("Current color is: ");
Serial.println(simonSays.currentSequence[positionDisplay]);
Serial.print("pos display: ");
Serial.println(positionDisplay);
positionDisplay += 1;
if (positionDisplay >= simonSays.currentSequenceLength)
{
positionDisplay = 0;
}
ticksTillNextColor=100;
}
}

@ -0,0 +1,68 @@
#include "SimonDisplay.h"
namespace{
SingleColor singleColor;
}
SimonDisplay::SimonDisplay(M5Atom &_m5) :
m5(_m5),
numberOfColors{2},
currentColor{0},
currentMode{0},
modeList{
&singleColor
}
{}
void SimonDisplay::begin()
{
baseColors[0] = CRGB::DarkGreen;
baseColors[1] = CRGB::DarkBlue;
baseColors[2] = CRGB::DarkOrange;
baseColors[3] = CRGB::Gold;
baseColors[4] = CRGB::DarkViolet;
baseColors[5] = CRGB(100, 100, 100);
baseColors[6] = CRGB::Maroon;
baseColors[7] = CRGB::DarkTurquoise;
baseColors[8] = CRGB::DeepPink;
highlightColors[0] = CRGB::Green;
highlightColors[1] = CRGB::Blue;
highlightColors[2] = CRGB::Orange;
highlightColors[3] = CRGB::Yellow;
highlightColors[4] = CRGB::Violet;
highlightColors[5] = CRGB::White;
highlightColors[6] = CRGB::Brown;
highlightColors[7] = CRGB::Turquoise;
highlightColors[8] = CRGB::Pink;
}
void SimonDisplay::update()
{
modeList[currentMode]->update(*this);
}
void SimonDisplay::setActiveColor(int _highlightColor)
{
currentColor=_highlightColor;
}
void SimonDisplay::drawSingleColor(int colorId, bool hightlightBool)
{
for (int i = 0; i <= 25; i++)
{
if (hightlightBool){
M5.dis.drawpix(i, highlightColors[colorId]);
}
else{
M5.dis.drawpix(i, baseColors[colorId]);
}
}
}
void SingleColor::update(SimonDisplay & simonDisplay)
{
// Display single current color
simonDisplay.drawSingleColor(simonDisplay.currentColor, false);
}

@ -0,0 +1,53 @@
#pragma once
#include <Arduino.h>
#include "M5Atom.h"
#include <FastLED.h>
class SimonDisplay;
class DisplayMode {
public:
virtual ~DisplayMode() {}
virtual void update(SimonDisplay & simonDisplay) {}
};
class SingleColor final : public DisplayMode {
public:
void update(SimonDisplay & simonDisplay) override;
};
class SimonDisplay {
public:
SimonDisplay(M5Atom & _m5);
~SimonDisplay() {};
void begin();
void update();
void setActiveColor(int _highlightColor);
void setColorSequence(int _colorSequence[10]);
void setDisplayMode(int _mode);
void setNumberColors(int _numberOfColors);
private:
M5Atom m5;
CRGB currentColors[9];
CRGB baseColors[9];
CRGB highlightColors[9];
int numberOfColors;
int currentColor;
int currentMode;
friend class SingleColor;
DisplayMode * modeList[1];
int currentSequence[10];
private:
// this is used with friends
void drawSingleColor(int colorId, bool hightlightBool);
};

@ -1,132 +1,44 @@
#include "SimonSays.h"
/* Some Logic to get the Variable type with serial print
// Generic catch-all implementation.
template <typename T_ty>
struct TypeInfo
{
static const char *name;
};
template <typename T_ty>
const char *TypeInfo<T_ty>::name = "unknown";
// Handy macro to make querying stuff easier.
#define TYPE_NAME(var) TypeInfo<typeof(var)>::name
// Handy macro to make defining stuff easier.
#define MAKE_TYPE_INFO(type) template <> \
const char *TypeInfo<type>::name = #type;
// Type-specific implementations.
MAKE_TYPE_INFO(int);
MAKE_TYPE_INFO(float);
MAKE_TYPE_INFO(short);
MAKE_TYPE_INFO(CRGB);
USAGE:
Serial.println(TYPE_NAME(variable));
*/
SimonSays::SimonSays(M5Atom &_m5device):
m5device(_m5device)
{
};
SimonSays::~SimonSays(){
// Anonymous namespace for states
};
namespace {
ShowColorSequence showColorSequence;
EnterColorSequence enterColorSequence;
void SimonSays::begin(uint8_t _currentLevel, uint8_t _numberColors)
{
currentLevel = _currentLevel;
numberColors = _numberColors;
}
baseColors[0] = CRGB::DarkGreen;
baseColors[1] = CRGB::DarkBlue;
baseColors[2] = CRGB::DarkOrange;
baseColors[3] = CRGB::Gold;
baseColors[4] = CRGB::DarkViolet;
baseColors[5] = CRGB(100,100,100);
baseColors[6] = CRGB::Maroon;
baseColors[7] = CRGB::DarkTurquoise;
baseColors[8] = CRGB::DeepPink;
SimonSays::SimonSays(SimonDisplay & _simonDisplay):
highlightColors[0] = CRGB::Green;
highlightColors[1] = CRGB::Blue;
highlightColors[2] = CRGB::Orange;
highlightColors[3] = CRGB::Yellow;
highlightColors[4] = CRGB::Violet;
highlightColors[5] = CRGB::White;
highlightColors[6] = CRGB::Brown;
highlightColors[7] = CRGB::Turquoise;
highlightColors[8] = CRGB::Pink;
stateList {
&showColorSequence,
&enterColorSequence
},
currentState{0},
// Copy colors from src to dest in length 9
memmove(&currentColors, &baseColors, 9 * sizeof(CRGB));
};
simonDisplay(_simonDisplay)
void SimonSays::advanceHighlightColor()
{
currentColors[currentColorId]=baseColors[currentColorId];
currentColorId++;
if (currentColorId >= numberColors)
{
currentColorId=0;
};
currentColors[currentColorId]=highlightColors[currentColorId];
// Serial.print("current Color: ");
// Serial.println(currentColorId);
return;
};
void SimonSays::checkBtnPress()
{
if (m5device.Btn.wasPressed()) {
Serial.println("Btn pressed");
if (currentColorId == 0) {
Serial.println("success");
}
else {
Serial.println("FAIL!");
}
stateList[currentState]->enter(*this);
}
void SimonSays::update() {
stateList[currentState]->update(*this);
}
void SimonSays::begin() {
// Some starting logic
currentSequenceLength = 9; // change this adjusting to level
generateNewSequence(); // This will generate a new random sequence.
stateList[currentState]->enter(*this);
}
void SimonSays::generateNewSequence() {
int maxId = 8;
// TODO: Make random sequence
int newSequence[10] = {0,1,2,3,4,5,6,7,8,8};
int length = sizeof(currentSequence)/sizeof(currentSequence[0]);
for (int i = 0; i < length; i++) {
currentSequence[i] = newSequence[i];
}
};
void SimonSays::update(uint32_t currentTime)
{
checkBtnPress();
if ((currentTime-lastActivationTime)>colorAdvanceTimeInMs) {
advanceHighlightColor();
lastActivationTime=currentTime;
}
// determine pattern von number color
switch (numberColors) {
case 2:
for (int i=0;i<=25;i++){
if (i%5==0 || (i-1)%5==0) {
M5.dis.drawpix(i, currentColors[0]);
}
else if ((i-3)%5==0 || (i-4)%5==0) {
M5.dis.drawpix(i,currentColors[1]);
}
else {
M5.dis.drawpix(i,CRGB::Black);
}
};
break;
default:
break;
};
// draw pattern
};
}

@ -1,34 +1,68 @@
#pragma once
#include <Arduino.h>
#include "M5Atom.h"
#include "SimonDisplay.h"
#include <FastLED.h>
// Introduce main class
class SimonSays;
class SimonSays
{
// Constructor class for all states of game
class GameState {
public:
SimonSays(M5Atom & m5device);
~SimonSays();
virtual ~GameState() {}
virtual void enter(SimonSays & simonSays) {}
virtual void update(SimonSays & simonSays) {}
virtual void leave(SimonSays & simonSays) const {}
};
M5Atom & m5device;
// Game classes build from this
class ShowColorSequence final : public GameState {
public:
ShowColorSequence();
void enter(SimonSays &simonSays) override;
void update(SimonSays &simonSays) override;
void leave(SimonSays &simonSays) const override {};
private:
// char *colors[] = {'0xcc0000','0x00cc00'};
// void _setDisplay();
CRGB currentColors[9];
CRGB baseColors[9];
CRGB highlightColors[9];
int positionDisplay;
int speed;
int ticksTillNextColor;
};
uint32_t lastActivationTime = 0;
class EnterColorSequence final : public GameState {
public:
void enter(SimonSays &simonSays) override {};
void update(SimonSays &simonSays) override {};
void leave(SimonSays &simonSays) const override {};
};
public:
int numberColors = 2;
int currentLevel = 0;
int currentColorId = 0;
uint32_t colorAdvanceTimeInMs = 2000;
void
begin(uint8_t currentLevel = 0, uint8_t numberColors = 2);
void update(uint32_t time);
void advanceHighlightColor();
void checkBtnPress();
// This is the main game class. Different states of the game are called from here.
class SimonSays
{
public:
SimonSays(SimonDisplay &simonDisplay);
~SimonSays() {};
// State logic
GameState *stateList[2];
int currentState;
// possible functions to call
void begin();
void selectNext();
void set();
void update();
// Game logic
int currentSequence[10];
int currentSequenceLength;
// Display device logic for LEDs etc
SimonDisplay &simonDisplay;
private:
void generateNewSequence();
};

@ -9,6 +9,7 @@
****************************************************************/
#include "M5Atom.h"
#include "SimonDisplay.h"
#include "SimonSays.h"
#include "MCUInfo.h"
@ -26,7 +27,9 @@ void setBuff(uint8_t Rdata, uint8_t Gdata, uint8_t Bdata)
}
}
SimonSays Simon(M5);
SimonDisplay simonDisplay(M5);
SimonSays Simon(simonDisplay);
uint32_t timeOfLastTick = 0;
@ -35,6 +38,7 @@ void setup()
M5.begin(true, false, true);
delay(10);
simonDisplay.begin();
Simon.begin();
// Initialize ticks
@ -52,7 +56,8 @@ void loop()
{
timeOfLastTick = time;
Simon.update(time);
Simon.update();
simonDisplay.update();
M5.update();
}

Loading…
Cancel
Save