diff --git a/src/main.cpp b/src/main.cpp index f5ce14097e7165d4b2f2b870a8ae9a6685bc7412..929b5842bab179c824fdc07b8b7030c520c8af3f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -21,16 +21,25 @@ void handleButton(); Task taskButton(TASK_IMMEDIATE, TASK_FOREVER, &handleButton); void handleStep(); Task taskStep(25, TASK_FOREVER, &handleStep); -void handleInternalLostAnimation(); -Task taskInternalLostAnimation(10, 100, &handleInternalLostAnimation); -void handleExternalLostAnimation(); -Task taskExternalLostAnimation(10, 100, &handleExternalLostAnimation); +void handleInternalMissedAnimation(); +Task taskInternalMissedAnimation(10, 100, &handleInternalMissedAnimation); +void handleExternalMissedAnimation(); +Task taskExternalMissedAnimation(10, 100, &handleExternalMissedAnimation); +void handleExternalWinAnimation(); +Task taskExternalWinAnimation(8, 2000, &handleExternalWinAnimation); +void handleInternalWinAnimation(); +Task taskInternalWinAnimation(8, 2000, &handleInternalWinAnimation); +void handleBlinkPoint(); +Task taskBlinkPoint(300, TASK_FOREVER, &handleBlinkPoint); -void doneLostAnimation(); +void doneMissedAnimation(); +void doneWinAnimation(); void internalMissed(); void externalMissed(); void setup() { + randomSeed(analogRead(0)); + pinMode(LED_BUILTIN, OUTPUT); pinMode(EXTERNAL_BUTTON_PIN_A, OUTPUT); @@ -47,10 +56,17 @@ void setup() { taskButton.enable(); scheduler.addTask(taskStep); taskStep.enable(); - scheduler.addTask(taskExternalLostAnimation); - taskExternalLostAnimation.setOnDisable(&doneLostAnimation); - scheduler.addTask(taskInternalLostAnimation); - taskInternalLostAnimation.setOnDisable(&doneLostAnimation); + scheduler.addTask(taskExternalMissedAnimation); + taskExternalMissedAnimation.setOnDisable(&doneMissedAnimation); + scheduler.addTask(taskInternalMissedAnimation); + taskInternalMissedAnimation.setOnDisable(&doneMissedAnimation); + + scheduler.addTask(taskExternalWinAnimation); + taskExternalWinAnimation.setOnDisable(&doneWinAnimation); + scheduler.addTask(taskInternalWinAnimation); + taskInternalWinAnimation.setOnDisable(&doneWinAnimation); + scheduler.addTask(taskBlinkPoint); + taskBlinkPoint.enable(); } void loop() { @@ -60,18 +76,38 @@ void loop() { int position = 0; int greenLength = 10; bool singlePlayer = true; +int pointsInternal = 0; +int pointsExternal = 0; +bool lastPointInternal = false; +bool hideLastPoint = false; #define STATE_PAUSE 0 #define STATE_FORWARD 1 #define STATE_BACKWARD 2 -#define STATE_LOST 3; +#define STATE_MISSED 3; +#define STATE_WIN 4; int state = STATE_PAUSE; void show() { - for (int i = 0; i < NEOPIXEL_LEN; i++) { - pixels.setPixelColor(i, 0); - } - if (state == STATE_FORWARD || state == STATE_BACKWARD) { + pixels.clear(); + if (state == STATE_PAUSE) { + int points = pointsInternal; + if (lastPointInternal && hideLastPoint) { + points = max(0, points - 1); + } + for (int i = 0; i < points; i++) { + pixels.setPixelColor(i, 0xFFFF00); + } + + points = pointsExternal; + if (!lastPointInternal && hideLastPoint) { + points = max(0, points - 1); + } + for (int i = NEOPIXEL_LEN - 1 - points; i < NEOPIXEL_LEN; i++) { + pixels.setPixelColor(i, 0xFFFF00); + } + + } else if (state == STATE_FORWARD || state == STATE_BACKWARD) { for (int i = 0; i < greenLength; i++) { pixels.setPixelColor(i, 0x00FF00); } @@ -91,8 +127,9 @@ void show() { int currentRound = 0; #define MAX_LEVEL 10 -int greenLengths[] = {10,10, 9, 8, 7, 6, 5, 5, 4, 4, 3}; -int stepIntervals[] = {25,25,20,18,16,14,12,10,10,10,10}; +#define NUM_LEVEL (MAX_LEVEL + 1) +int greenLengths[NUM_LEVEL] = {10,10, 9, 8, 7, 6, 5, 5, 4, 4, 3}; +int stepIntervals[NUM_LEVEL] = {25,25,20,18,16,14,12,10,10,10,10}; void setRound(int newRound) { currentRound = newRound; @@ -160,22 +197,18 @@ void handleButton() { singlePlayer = digitalRead(EXTERNAL_BUTTON_PIN_NO) == LOW; } -void handleExternalLostAnimation() { - int step = (100 - taskExternalLostAnimation.getIterations()) % 25; - for (int i = 0; i < NEOPIXEL_LEN; i++) { - pixels.setPixelColor(i, 0); - } +void handleExternalMissedAnimation() { + int step = (100 - taskExternalMissedAnimation.getIterations()) % 25; + pixels.clear(); for (int i = NEOPIXEL_LEN - 1 - 25; i < NEOPIXEL_LEN - 25 + step; i++) { pixels.setPixelColor(i, 0xFF0000); } pixels.show(); } -void handleInternalLostAnimation() { - int step = (100 - taskInternalLostAnimation.getIterations()) % 25; - for (int i = 0; i < NEOPIXEL_LEN; i++) { - pixels.setPixelColor(i, 0); - } +void handleInternalMissedAnimation() { + int step = (100 - taskInternalMissedAnimation.getIterations()) % 25; + pixels.clear(); for (int i = 25 - step; i < 25; i++) { pixels.setPixelColor(i, 0xFF0000); } @@ -183,21 +216,31 @@ void handleInternalLostAnimation() { } void externalMissed() { - state = STATE_LOST; - taskExternalLostAnimation.restart(); + state = STATE_MISSED; + pointsInternal += 1; + lastPointInternal = true; + taskExternalMissedAnimation.restart(); } void internalMissed() { - state = STATE_LOST; - taskInternalLostAnimation.restart(); + state = STATE_MISSED; + pointsExternal += 1; + lastPointInternal = false; + taskInternalMissedAnimation.restart(); } -void doneLostAnimation() { +void doneMissedAnimation() { state = STATE_PAUSE; + if (pointsExternal >= 7) { + state = STATE_WIN; + taskExternalWinAnimation.restart(); + } else if (pointsInternal >= 7) { + state = STATE_WIN; + taskInternalWinAnimation.restart(); + } } void handleStep() { - unsigned long now = millis(); switch (state) { case STATE_PAUSE: show(); @@ -228,3 +271,96 @@ void handleStep() { break; } } + +void handleBlinkPoint() { + hideLastPoint = !hideLastPoint; +} + +#define NUM_WIN_POSITIONS 10 +int winPositions[NUM_WIN_POSITIONS] = {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1}; +uint32_t winColors[NUM_WIN_POSITIONS]; +int winLengths[NUM_WIN_POSITIONS]; +int untilSpawn = 0; + +#define NUM_COLORS 6 +uint32_t colors[NUM_COLORS] = {0xFF0000, 0x00FF00, 0x0000FF, 0xFF00FF, 0x00FFFF, 0xFFFF00}; + +void setPixelAnimation(int i, uint32_t color, bool reverse) { + if (reverse) { + i = NEOPIXEL_LEN - 1 - i; + } + pixels.setPixelColor(i, color); +} + +void handleWinAnimation(bool external) { + // progress + for (int i = 0; i < NUM_WIN_POSITIONS; i++) { + if (winPositions[i] >= 0) { + if (winLengths[i] == 0) { + winPositions[i] += 1; + if (winPositions[i] > 30 && random(10) == 0) { + winLengths[i] += 1; + } + } else if (winLengths[i] > 0) { + winLengths[i] += 1; + if (winLengths[i] >= 10 && random(10) == 0) { + winPositions[i] = -1; + winLengths[i] = 0; + } + } + } + } + // spawn + if (untilSpawn <= 0 && random(10) == 0) { + for (int i = 0; i < NUM_WIN_POSITIONS; i++) { + if (winPositions[i] == -1) { + winPositions[i] = 7; + winLengths[i] = 0; + winColors[i] = colors[random(NUM_COLORS)]; + break; + } + } + untilSpawn = 22; + } + untilSpawn -= 1; + // show + pixels.clear(); + for (int i = 0; i < NUM_WIN_POSITIONS; i++) { + if (winPositions[i] >= 0) { + if (winLengths[i] == 0) { + setPixelAnimation(winPositions[i], 0xFFFF00, external); + } else { + for (int k = winLengths[i]; k > 0; k -= 10) { + setPixelAnimation(winPositions[i] - k, winColors[i], external); + setPixelAnimation(winPositions[i] + k, winColors[i], external); + } + } + } + } + // show points + for (int i = 0; i < pointsInternal; i++) { + pixels.setPixelColor(i, 0xFFFF00); + } + for (int i = NEOPIXEL_LEN - 1 - pointsExternal; i < NEOPIXEL_LEN; i++) { + pixels.setPixelColor(i, 0xFFFF00); + } + pixels.show(); +} + +void handleExternalWinAnimation() { + handleWinAnimation(true); +} + +void handleInternalWinAnimation() { + handleWinAnimation(false); +} + +void doneWinAnimation() { + pointsExternal = 0; + pointsInternal = 0; + lastPointInternal = false; + state = STATE_PAUSE; + for (int i = 0; i < NUM_WIN_POSITIONS; i++) { + winPositions[i] = -1; + } +}