NewYear
This commit is contained in:
parent
72e5946a0e
commit
2351c42db2
@ -30,4 +30,4 @@ add_custom_target(
|
|||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
)
|
)
|
||||||
|
|
||||||
add_executable(Z_DUMMY_TARGET ${SRC_LIST} src/mode/Test/Border.h src/mode/Clock/Clock.h src/mode/SpaceInvaders/SpaceInvaders.h src/mode/Timer.h src/mode/Pong/Pong.cpp src/BASICS.cpp src/display/Display.cpp)
|
add_executable(Z_DUMMY_TARGET ${SRC_LIST} src/mode/Test/Border.h src/mode/Clock/Clock.h src/mode/SpaceInvaders/SpaceInvaders.h src/mode/Timer.h src/mode/Pong/Pong.cpp src/BASICS.cpp src/display/Display.cpp src/mode/NewYear/NewYear.h src/mode/NewYear/Firework.h src/mode/NewYear/NewYear.cpp)
|
||||||
|
|||||||
@ -13,9 +13,9 @@ platform = espressif32
|
|||||||
board = esp32dev
|
board = esp32dev
|
||||||
framework = arduino
|
framework = arduino
|
||||||
lib_deps = https://github.com/adafruit/Adafruit_NeoPixel
|
lib_deps = https://github.com/adafruit/Adafruit_NeoPixel
|
||||||
upload_port = 10.0.0.120
|
;upload_port = 10.0.0.120
|
||||||
upload_protocol = espota
|
;upload_protocol = espota
|
||||||
;upload_port = /dev/ttyUSB0
|
upload_port = /dev/ttyUSB0
|
||||||
;upload_speed = 921600
|
upload_speed = 921600
|
||||||
monitor_port = /dev/ttyUSB0
|
monitor_port = /dev/ttyUSB0
|
||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
|
|||||||
@ -1,20 +1,10 @@
|
|||||||
#include "BASICS.h"
|
#include "BASICS.h"
|
||||||
|
|
||||||
double step(double valueCurrent, double valueMin, double valueMax, microseconds_t timeTotal, microseconds_t timeDelta) {
|
double doStep(double valueCurrent, double valueMin, double valueMax, long long millisecondsTotal, microseconds_t microsecondsDelta) {
|
||||||
double valueRange = valueMax - valueMin;
|
double valueRange = valueMax - valueMin;
|
||||||
double timeRatio = (double) timeDelta / (double) timeTotal;
|
double timeRatio = (double) microsecondsDelta / ((double) millisecondsTotal * 1000.0);
|
||||||
double valueStep = valueRange * timeRatio;
|
double valueStep = valueRange * timeRatio;
|
||||||
double valueNew = max(valueMin, min(valueMax, valueCurrent + valueStep));
|
double valueNew = max(valueMin, min(valueMax, valueCurrent + valueStep));
|
||||||
// Serial.printf("valueCurrent: %13.3f\n", valueCurrent);
|
|
||||||
// Serial.printf("valueMin: %13.3f\n", valueMin);
|
|
||||||
// Serial.printf("valueMax: %13.3f\n", valueMax);
|
|
||||||
// Serial.printf("valueRange: %13.3f\n", valueRange);
|
|
||||||
// Serial.printf("timeTotal: %13.3f\n", (double) timeTotal);
|
|
||||||
// Serial.printf("timeDelta: %13.3f\n", (double) timeDelta);
|
|
||||||
// Serial.printf("timeRatio: %13.3f\n", timeRatio);
|
|
||||||
// Serial.printf("valueStep: %13.3f\n", valueStep);
|
|
||||||
// Serial.printf("valueNew: %13.3f\n", valueNew);
|
|
||||||
// Serial.println();
|
|
||||||
return valueNew;
|
return valueNew;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
typedef int64_t microseconds_t;
|
typedef int64_t microseconds_t;
|
||||||
|
|
||||||
double step(double valueCurrent, double valueMin, double valueMax, microseconds_t timeTotal, microseconds_t timeDelta);
|
double doStep(double valueCurrent, double valueMin, double valueMax, microseconds_t millisecondsTotal, microseconds_t microsecondsDelta);
|
||||||
|
|
||||||
bool randomBool(int uncertainty);
|
bool randomBool(int uncertainty);
|
||||||
|
|
||||||
|
|||||||
@ -3,11 +3,24 @@
|
|||||||
|
|
||||||
#include "Pixel.h"
|
#include "Pixel.h"
|
||||||
#include "Adafruit_NeoPixel.h"
|
#include "Adafruit_NeoPixel.h"
|
||||||
|
#include "Vector.h"
|
||||||
|
|
||||||
#define SYMBOL_COUNT 13
|
#define SYMBOL_COUNT 13
|
||||||
#define DISPLAY_CHAR_WIDTH 3
|
#define DISPLAY_CHAR_WIDTH 3
|
||||||
#define DISPLAY_CHAR_HEIGHT 5
|
#define DISPLAY_CHAR_HEIGHT 5
|
||||||
|
|
||||||
|
#define FULL 255
|
||||||
|
#define ____ 0
|
||||||
|
#define rgb(r, g, b) ((((r << 8) | g) << 8) | b)
|
||||||
|
#define COLOR_RED (rgb(FULL, ____, ____))
|
||||||
|
#define COLOR_GREEN (rgb(____, FULL, ____))
|
||||||
|
#define COLOR_BLUE (rgb(____, ____, FULL))
|
||||||
|
#define COLOR_YELLOW (rgb(FULL, FULL, ____))
|
||||||
|
#define COLOR_VIOLET (rgb(FULL, ____, FULL))
|
||||||
|
#define COLOR_TURQUOISE (rgb(____, FULL, FULL))
|
||||||
|
#define COLOR_WHITE (rgb(FULL, FULL, FULL))
|
||||||
|
#define COLOR_BLACK (rgb(____, ____, ____))
|
||||||
|
|
||||||
extern bool SYMBOLS[SYMBOL_COUNT][DISPLAY_CHAR_WIDTH * DISPLAY_CHAR_HEIGHT];
|
extern bool SYMBOLS[SYMBOL_COUNT][DISPLAY_CHAR_WIDTH * DISPLAY_CHAR_HEIGHT];
|
||||||
|
|
||||||
class Display {
|
class Display {
|
||||||
@ -51,6 +64,10 @@ public:
|
|||||||
print(xPos, yPos, index, 255, 255, 255);
|
print(xPos, yPos, index, 255, 255, 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void print(uint8_t *xPos, uint8_t yPos, uint8_t index, uint32_t color) {
|
||||||
|
print(xPos, yPos, index, (uint8_t) (color >> 16), (uint8_t) (color >> 8), (uint8_t) color);
|
||||||
|
}
|
||||||
|
|
||||||
void print(uint8_t *xPos, uint8_t yPos, uint8_t index, uint8_t r, uint8_t g, uint8_t b) {
|
void print(uint8_t *xPos, uint8_t yPos, uint8_t index, uint8_t r, uint8_t g, uint8_t b) {
|
||||||
if (index >= SYMBOL_COUNT) {
|
if (index >= SYMBOL_COUNT) {
|
||||||
Serial.printf("Cannot print symbol #%u.\n", index);
|
Serial.printf("Cannot print symbol #%u.\n", index);
|
||||||
@ -77,6 +94,14 @@ public:
|
|||||||
setPixelColor(x, y, (((r << 8) | g) << 8) | b);
|
setPixelColor(x, y, (((r << 8) | g) << 8) | b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set(Vector *pos, uint32_t color) {
|
||||||
|
setPixelColor((uint8_t) round(pos->x), (uint8_t) round(pos->y), color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set(Vector *pos, uint8_t r, uint8_t g, uint8_t b) {
|
||||||
|
setPixelColor((uint8_t) round(pos->x), (uint8_t) round(pos->y), (((r << 8) | g) << 8) | b);
|
||||||
|
}
|
||||||
|
|
||||||
void setPixelColor(uint8_t x, uint8_t y, uint32_t color) {
|
void setPixelColor(uint8_t x, uint8_t y, uint32_t color) {
|
||||||
if (x >= width || y >= height) {
|
if (x >= width || y >= height) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -11,6 +11,11 @@ public:
|
|||||||
|
|
||||||
double y;
|
double y;
|
||||||
|
|
||||||
|
Vector() :
|
||||||
|
x(0.0), y(0.0) {
|
||||||
|
// nothing
|
||||||
|
}
|
||||||
|
|
||||||
Vector(double x, double y) :
|
Vector(double x, double y) :
|
||||||
x(x), y(y) {
|
x(x), y(y) {
|
||||||
// nothing
|
// nothing
|
||||||
@ -22,6 +27,24 @@ public:
|
|||||||
y = sin(radians) * length;
|
y = sin(radians) * length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector *set(Vector that) {
|
||||||
|
this->x = that.x;
|
||||||
|
this->y = that.y;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector *set(double _x, double _y) {
|
||||||
|
this->x = _x;
|
||||||
|
this->y = _y;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector *add(double _x, double _y) {
|
||||||
|
this->x += _x;
|
||||||
|
this->y += _y;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
Vector *add(Vector that) {
|
Vector *add(Vector that) {
|
||||||
this->x += that.x;
|
this->x += that.x;
|
||||||
this->y += that.y;
|
this->y += that.y;
|
||||||
@ -45,7 +68,6 @@ public:
|
|||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
66
src/main.cpp
66
src/main.cpp
@ -1,15 +1,21 @@
|
|||||||
#include <WiFi.h>
|
#include <WiFi.h>
|
||||||
#include <ArduinoOTA.h>
|
#include <ArduinoOTA.h>
|
||||||
#include "mode/Mode.h"
|
#include "mode/Mode.h"
|
||||||
#include "mode/GameOfLife/GameOfLife.h"
|
|
||||||
#include "display/Display.h"
|
#include "display/Display.h"
|
||||||
|
|
||||||
|
#if PROG_ALL
|
||||||
|
#include "mode/GameOfLife/GameOfLife.h"
|
||||||
#include "mode/Pong/Pong.h"
|
#include "mode/Pong/Pong.h"
|
||||||
#include "mode/Test/Border.h"
|
#include "mode/Test/Border.h"
|
||||||
#include "mode/Clock/Clock.h"
|
#include "mode/Clock/Clock.h"
|
||||||
#include "mode/SpaceInvaders/SpaceInvaders.h"
|
#include "mode/SpaceInvaders/SpaceInvaders.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "mode/NewYear/NewYear.h"
|
||||||
|
|
||||||
enum ModeId {
|
enum ModeId {
|
||||||
NONE,
|
NONE,
|
||||||
|
#if PROG_ALL
|
||||||
BORDER,
|
BORDER,
|
||||||
CLOCK,
|
CLOCK,
|
||||||
GAME_OF_LIFE_BLACK_WHITE,
|
GAME_OF_LIFE_BLACK_WHITE,
|
||||||
@ -18,11 +24,13 @@ enum ModeId {
|
|||||||
GAME_OF_LIFE_RANDOM_COLOR,
|
GAME_OF_LIFE_RANDOM_COLOR,
|
||||||
PONG,
|
PONG,
|
||||||
SPACE_INVADERS,
|
SPACE_INVADERS,
|
||||||
|
#endif
|
||||||
|
NEW_YEAR,
|
||||||
};
|
};
|
||||||
|
|
||||||
Display display(32, 8);
|
Display display(32, 8);
|
||||||
|
|
||||||
ModeId newModeId = PONG;
|
ModeId newModeId = NEW_YEAR;
|
||||||
|
|
||||||
ModeId currentModeId = NONE;
|
ModeId currentModeId = NONE;
|
||||||
|
|
||||||
@ -48,6 +56,7 @@ void setup() {
|
|||||||
delay(500);
|
delay(500);
|
||||||
Serial.begin(115200);
|
Serial.begin(115200);
|
||||||
Serial.println("\n\n\nStartup!");
|
Serial.println("\n\n\nStartup!");
|
||||||
|
|
||||||
WiFi.begin("HappyNet", "1Grausame!Sackratte7");
|
WiFi.begin("HappyNet", "1Grausame!Sackratte7");
|
||||||
ArduinoOTA.onStart([]() {
|
ArduinoOTA.onStart([]() {
|
||||||
display.clear();
|
display.clear();
|
||||||
@ -68,8 +77,8 @@ void setup() {
|
|||||||
display.clear();
|
display.clear();
|
||||||
display.loop();
|
display.loop();
|
||||||
});
|
});
|
||||||
|
|
||||||
ArduinoOTA.begin();
|
ArduinoOTA.begin();
|
||||||
|
|
||||||
display.setup();
|
display.setup();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,29 +165,34 @@ void loadNewMode() {
|
|||||||
switch (currentModeId) {
|
switch (currentModeId) {
|
||||||
case NONE:
|
case NONE:
|
||||||
break;
|
break;
|
||||||
case BORDER:
|
#if PROG_ALL
|
||||||
mode = new Border(&display);
|
case BORDER:
|
||||||
break;
|
mode = new Border(&display);
|
||||||
case CLOCK:
|
break;
|
||||||
mode = new Clock(&display);
|
case CLOCK:
|
||||||
break;
|
mode = new Clock(&display);
|
||||||
case GAME_OF_LIFE_BLACK_WHITE:
|
break;
|
||||||
mode = new GameOfLife(&display, BLACK_WHITE);
|
case GAME_OF_LIFE_BLACK_WHITE:
|
||||||
break;
|
mode = new GameOfLife(&display, BLACK_WHITE);
|
||||||
case GAME_OF_LIFE_GRAYSCALE:
|
break;
|
||||||
mode = new GameOfLife(&display, GRAYSCALE);
|
case GAME_OF_LIFE_GRAYSCALE:
|
||||||
break;
|
mode = new GameOfLife(&display, GRAYSCALE);
|
||||||
case GAME_OF_LIFE_COLOR_FADE:
|
break;
|
||||||
mode = new GameOfLife(&display, COLOR_FADE);
|
case GAME_OF_LIFE_COLOR_FADE:
|
||||||
break;
|
mode = new GameOfLife(&display, COLOR_FADE);
|
||||||
case GAME_OF_LIFE_RANDOM_COLOR:
|
break;
|
||||||
mode = new GameOfLife(&display, RANDOM_COLOR);
|
case GAME_OF_LIFE_RANDOM_COLOR:
|
||||||
break;
|
mode = new GameOfLife(&display, RANDOM_COLOR);
|
||||||
case PONG:
|
break;
|
||||||
mode = new Pong(&display);
|
case PONG:
|
||||||
break;
|
mode = new Pong(&display);
|
||||||
case SPACE_INVADERS:
|
break;
|
||||||
mode = new SpaceInvaders(&display);
|
case SPACE_INVADERS:
|
||||||
|
mode = new SpaceInvaders(&display);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
case NEW_YEAR:
|
||||||
|
mode = new NewYear(&display);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Serial.printf("Mode: %s\n", mode == nullptr ? "None" : mode->getName());
|
Serial.printf("Mode: %s\n", mode == nullptr ? "None" : mode->getName());
|
||||||
|
|||||||
@ -16,15 +16,10 @@ public:
|
|||||||
void animate(microseconds_t dt) {
|
void animate(microseconds_t dt) {
|
||||||
// TODO "doStep" does not work as expected
|
// TODO "doStep" does not work as expected
|
||||||
if (alive) {
|
if (alive) {
|
||||||
fade = step(fade, 0.0, 255.0, 200000, +dt);
|
fade = doStep(fade, 0.0, 255.0, 200, +dt);
|
||||||
} else {
|
} else {
|
||||||
fade = step(fade, 0.0, 255.0, 200000, -dt);
|
fade = doStep(fade, 0.0, 255.0, 200, -dt);
|
||||||
}
|
}
|
||||||
// if (alive) {
|
|
||||||
// fade = min(255.0, fade + (double) dt / 200000.0);
|
|
||||||
// } else {
|
|
||||||
// fade = max(0.0, fade - (double) dt / 200000.0);
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t getR() const {
|
uint8_t getR() const {
|
||||||
|
|||||||
@ -47,12 +47,11 @@ protected:
|
|||||||
|
|
||||||
virtual void doStep(microseconds_t dt) {};
|
virtual void doStep(microseconds_t dt) {};
|
||||||
|
|
||||||
Timer *createTimer(microseconds_t interval, Timer::Callback callback) {
|
Timer *createTimer(long long millisecondsInterval, Timer::Callback callback) {
|
||||||
for (Timer **timer = timers; timer < timers + TIMER_COUNT; timer++) {
|
for (Timer **timer = timers; timer < timers + TIMER_COUNT; timer++) {
|
||||||
if (*timer == nullptr) {
|
if (*timer == nullptr) {
|
||||||
*timer = new Timer(interval, callback);
|
*timer = new Timer(millisecondsInterval * 1000, callback);
|
||||||
timerCount++;
|
timerCount++;
|
||||||
Serial.printf("Timer created: %p (having %u now)\n", *timer, timerCount);
|
|
||||||
return *timer;
|
return *timer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -84,7 +83,6 @@ private:
|
|||||||
void _destroyTimer(Timer **timer) {
|
void _destroyTimer(Timer **timer) {
|
||||||
timerCount--;
|
timerCount--;
|
||||||
free(*timer);
|
free(*timer);
|
||||||
Serial.printf("Timer destroyed: %p (having %u now)\n", *timer, timerCount);
|
|
||||||
*timer = nullptr;
|
*timer = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
136
src/mode/NewYear/Firework.h
Normal file
136
src/mode/NewYear/Firework.h
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
#ifndef NEW_YEAR_FIREWORK_H
|
||||||
|
#define NEW_YEAR_FIREWORK_H
|
||||||
|
|
||||||
|
#include "BASICS.h"
|
||||||
|
#include "display/Vector.h"
|
||||||
|
#include "display/Display.h"
|
||||||
|
|
||||||
|
class Firework {
|
||||||
|
|
||||||
|
enum State {
|
||||||
|
INITIAL, RISE, EXPLODE, SPARKLE
|
||||||
|
};
|
||||||
|
|
||||||
|
Display *display{};
|
||||||
|
|
||||||
|
uint32_t color{};
|
||||||
|
|
||||||
|
State state = RISE;
|
||||||
|
|
||||||
|
Vector position;
|
||||||
|
|
||||||
|
double destinationHeight = 0;
|
||||||
|
|
||||||
|
double explosionRadius = 0;
|
||||||
|
|
||||||
|
double sparkleMax = 0;
|
||||||
|
|
||||||
|
double explosion{};
|
||||||
|
|
||||||
|
double sparkle{};
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
void init(Display *_display) {
|
||||||
|
this->display = _display;
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset() {
|
||||||
|
position.set((double) random(display->width), display->height);
|
||||||
|
color = random(16777216);
|
||||||
|
state = INITIAL;
|
||||||
|
|
||||||
|
destinationHeight = display->height / 2.0 + (double) random(5) - 2;
|
||||||
|
explosionRadius = (double) random(3) + 1;
|
||||||
|
sparkleMax = 100;
|
||||||
|
|
||||||
|
explosion = 0.0;
|
||||||
|
sparkle = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void launch() {
|
||||||
|
if (state != INITIAL) {
|
||||||
|
Serial.println("ERROR: Cannot start Firework. Already started.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
state = RISE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void step(microseconds_t dt) {
|
||||||
|
switch (state) {
|
||||||
|
case INITIAL:
|
||||||
|
break;
|
||||||
|
case RISE:
|
||||||
|
if (position.y <= destinationHeight) {
|
||||||
|
state = EXPLODE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EXPLODE:
|
||||||
|
if (explosion >= explosionRadius) {
|
||||||
|
state = SPARKLE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SPARKLE:
|
||||||
|
if (sparkle >= sparkleMax) {
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
switch (state) {
|
||||||
|
case INITIAL:
|
||||||
|
break;
|
||||||
|
case RISE:
|
||||||
|
position.y = doStep(position.y, 0.0, display->height, 1000, -dt);
|
||||||
|
break;
|
||||||
|
case EXPLODE:
|
||||||
|
explosion = doStep(explosion, 0.0, explosionRadius, 500, +dt);
|
||||||
|
break;
|
||||||
|
case SPARKLE:
|
||||||
|
sparkle = doStep(sparkle, 0.0, sparkleMax, 1000, +dt);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw() {
|
||||||
|
Vector p;
|
||||||
|
switch (state) {
|
||||||
|
case INITIAL:
|
||||||
|
break;
|
||||||
|
case RISE:
|
||||||
|
display->set(&position, COLOR_YELLOW);
|
||||||
|
break;
|
||||||
|
case EXPLODE:
|
||||||
|
drawParticle(p, +0.0, +1.0);
|
||||||
|
drawParticle(p, +0.7, +0.7);
|
||||||
|
drawParticle(p, +1.0, +0.0);
|
||||||
|
drawParticle(p, +0.7, -0.7);
|
||||||
|
drawParticle(p, +0.0, -1.0);
|
||||||
|
drawParticle(p, -0.7, -0.7);
|
||||||
|
drawParticle(p, -1.0, +0.0);
|
||||||
|
drawParticle(p, -0.7, +0.7);
|
||||||
|
break;
|
||||||
|
case SPARKLE:
|
||||||
|
if (randomBool(2)) drawParticle(p, +0.0, +1.0);
|
||||||
|
if (randomBool(2)) drawParticle(p, +0.7, +0.7);
|
||||||
|
if (randomBool(2)) drawParticle(p, +1.0, +0.0);
|
||||||
|
if (randomBool(2)) drawParticle(p, +0.7, -0.7);
|
||||||
|
if (randomBool(2)) drawParticle(p, +0.0, -1.0);
|
||||||
|
if (randomBool(2)) drawParticle(p, -0.7, -0.7);
|
||||||
|
if (randomBool(2)) drawParticle(p, -1.0, +0.0);
|
||||||
|
if (randomBool(2)) drawParticle(p, -0.7, +0.7);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawParticle(Vector &p, double x, double y) {
|
||||||
|
display->set(p.set(position)->add(x * explosion, y * explosion), color);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isAlive() {
|
||||||
|
return state != INITIAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
3
src/mode/NewYear/NewYear.cpp
Normal file
3
src/mode/NewYear/NewYear.cpp
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#include "NewYear.h"
|
||||||
|
|
||||||
|
NewYear *NewYear::instance = nullptr;
|
||||||
120
src/mode/NewYear/NewYear.h
Normal file
120
src/mode/NewYear/NewYear.h
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
#ifndef NEWYEAR_H
|
||||||
|
#define NEWYEAR_H
|
||||||
|
|
||||||
|
#define MAX_FIREWORKS 10
|
||||||
|
|
||||||
|
#include "mode/Mode.h"
|
||||||
|
#include "Firework.h"
|
||||||
|
|
||||||
|
class NewYear : public Mode {
|
||||||
|
|
||||||
|
static NewYear *instance;
|
||||||
|
|
||||||
|
Firework fireworksBegin[MAX_FIREWORKS];
|
||||||
|
Firework *fireworksEnd = fireworksBegin + MAX_FIREWORKS;
|
||||||
|
|
||||||
|
void launch(Timer *timer, uint32_t counter, uint32_t currentCount) {
|
||||||
|
for (Firework *firework = fireworksBegin; firework < fireworksEnd; firework++) {
|
||||||
|
if (!firework->isAlive()) {
|
||||||
|
firework->launch();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void step(Timer *timer, uint32_t counter, uint32_t currentCount) {
|
||||||
|
display->clear();
|
||||||
|
tm t{};
|
||||||
|
getLocalTime(&t);
|
||||||
|
int year = t.tm_year + 1900;
|
||||||
|
int mon = t.tm_mon + 1;
|
||||||
|
int day = t.tm_mday;
|
||||||
|
int hour = t.tm_hour;
|
||||||
|
int min = t.tm_min;
|
||||||
|
int sec = t.tm_sec;
|
||||||
|
#if PROG_ALL
|
||||||
|
#else
|
||||||
|
hour = 23;
|
||||||
|
min = 59;
|
||||||
|
sec = 55 + (int) (counter * 50 / 1000);
|
||||||
|
while (sec >= 60) {
|
||||||
|
min++;
|
||||||
|
sec -= 60;
|
||||||
|
}
|
||||||
|
while (min >= 60) {
|
||||||
|
hour++;
|
||||||
|
min -= 60;
|
||||||
|
}
|
||||||
|
while (hour >= 24) {
|
||||||
|
day++;
|
||||||
|
hour -= 24;
|
||||||
|
}
|
||||||
|
while (day > 31) {
|
||||||
|
mon++;
|
||||||
|
day -= 31;
|
||||||
|
}
|
||||||
|
while (mon > 12) {
|
||||||
|
year++;
|
||||||
|
mon -= 12;
|
||||||
|
}
|
||||||
|
Serial.printf("%04i-%02i-%02i %02i:%02i:%02i\n", year, mon, day, hour, min, sec);
|
||||||
|
#endif
|
||||||
|
if (mon == 12 && day == 31) {
|
||||||
|
size_t h = (24 - hour - (min > 0 || sec > 0 ? 1 : 0));
|
||||||
|
size_t m = (60 - min - (sec > 0 ? 1 : 0)) % 60;
|
||||||
|
size_t s = (60 - sec) % 60;
|
||||||
|
uint8_t x = 0;
|
||||||
|
if (h >= 10) {
|
||||||
|
display->print(&x, 1, h / 10, COLOR_WHITE);
|
||||||
|
} else {
|
||||||
|
x += 3;
|
||||||
|
}
|
||||||
|
x++;
|
||||||
|
display->print(&x, 1, h % 10, COLOR_WHITE);
|
||||||
|
display->print(&x, 1, 10, COLOR_WHITE);
|
||||||
|
display->print(&x, 1, m / 10, COLOR_WHITE);
|
||||||
|
x++;
|
||||||
|
display->print(&x, 1, m % 10, COLOR_WHITE);
|
||||||
|
display->print(&x, 1, 10, COLOR_WHITE);
|
||||||
|
display->print(&x, 1, s / 10, COLOR_WHITE);
|
||||||
|
x++;
|
||||||
|
display->print(&x, 1, s % 10, COLOR_WHITE);
|
||||||
|
} else {
|
||||||
|
for (Firework *firework = fireworksBegin; firework < fireworksEnd; firework++) {
|
||||||
|
if (firework->isAlive()) {
|
||||||
|
firework->step(timer->interval);
|
||||||
|
firework->draw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uint8_t x = 8;
|
||||||
|
display->print(&x, 1, year / 1000 % 10, counter % 64 != 0 ? COLOR_WHITE : COLOR_BLACK);
|
||||||
|
x++;
|
||||||
|
display->print(&x, 1, year / 100 % 10, counter % 64 != 1 ? COLOR_WHITE : COLOR_BLACK);
|
||||||
|
x++;
|
||||||
|
display->print(&x, 1, year / 10 % 10, counter % 64 != 2 ? COLOR_WHITE : COLOR_BLACK);
|
||||||
|
x++;
|
||||||
|
display->print(&x, 1, year / 1 % 10, counter % 64 != 3 ? COLOR_WHITE : COLOR_BLACK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit NewYear(Display *display) :
|
||||||
|
Mode(display) {
|
||||||
|
createTimer(500, [](Timer *timer, uint32_t counter, uint32_t currentCount) { instance->launch(timer, counter, currentCount); });
|
||||||
|
createTimer(50, [](Timer *timer, uint32_t counter, uint32_t currentCount) { instance->step(timer, counter, currentCount); });
|
||||||
|
instance = this;
|
||||||
|
for (Firework *firework = fireworksBegin; firework < fireworksEnd; firework++) {
|
||||||
|
firework->init(display);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~NewYear() override = default;
|
||||||
|
|
||||||
|
const char *getName() override {
|
||||||
|
return "NewYear";
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -133,7 +133,7 @@ public:
|
|||||||
position(display->width / 2.0, display->height / 2.0),
|
position(display->width / 2.0, display->height / 2.0),
|
||||||
velocity(random(360), exp10(1)) {
|
velocity(random(360), exp10(1)) {
|
||||||
instance = this;
|
instance = this;
|
||||||
createTimer(100000, &tick);
|
createTimer(100, &tick);
|
||||||
spawnBall(random(2) == 0 ? -1 : +1);
|
spawnBall(random(2) == 0 ? -1 : +1);
|
||||||
resetPlayer();
|
resetPlayer();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -31,8 +31,9 @@ public:
|
|||||||
accu += dt;
|
accu += dt;
|
||||||
if (accu >= interval) {
|
if (accu >= interval) {
|
||||||
uint32_t currentCount = accu / interval;
|
uint32_t currentCount = accu / interval;
|
||||||
|
totalCount += currentCount;
|
||||||
accu = accu % interval;
|
accu = accu % interval;
|
||||||
callback(this, totalCount++, currentCount);
|
callback(this, totalCount, currentCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user