Starfield

This commit is contained in:
Patrick Haßel 2023-01-03 18:43:31 +01:00
parent 82445efda4
commit eaf3dcea91
8 changed files with 114 additions and 60 deletions

View File

@ -107,8 +107,8 @@ public:
return DISPLAY_CHAR_WIDTH; return DISPLAY_CHAR_WIDTH;
} }
void set(Vector *pos, Color color) { void set(Vector pos, Color color) {
set((uint8_t) round(pos->x), (uint8_t) round(pos->y), color); set((uint8_t) round(pos.x), (uint8_t) round(pos.y), color);
} }
void set(uint8_t x, uint8_t y, Color color) { void set(uint8_t x, uint8_t y, Color color) {

View File

@ -11,63 +11,66 @@ public:
double y; double y;
double length;
Vector() : Vector() :
x(0.0), y(0.0) { x(0.0), y(0.0), length(0.0) {
// nothing // nothing
} }
Vector(double x, double y) : Vector(double x, double y) :
x(x), y(y) { x(x), y(y), length(sqrt(x * x + y * y)) {
// nothing // nothing
} }
Vector(long degrees, double length) { static Vector polar(long degrees, double length) {
double radians = (double) degrees * DEG_TO_RAD; double radians = (double) degrees * DEG_TO_RAD;
x = cos(radians) * length; return {
y = sin(radians) * length; cos(radians) * length,
sin(radians) * length,
};
} }
Vector *set(Vector that) { Vector plus(double _x, double _y) const {
this->x = that.x; return {x + _x, y + _y};
this->y = that.y;
return this;
} }
Vector *set(double _x, double _y) { Vector plus(Vector vector) const {
this->x = _x; return {x + vector.x, y + vector.y};
this->y = _y;
return this;
} }
Vector *add(double _x, double _y) { Vector minus(double _x, double _y) const {
this->x += _x; return {x - _x, y - _y};
this->y += _y;
return this;
} }
Vector *add(Vector that) { Vector minus(Vector vector) const {
this->x += that.x; return {x - vector.x, y - vector.y};
this->y += that.y;
return this;
} }
Vector *bounceInBox(uint8_t width, uint8_t height) { Vector multiply(double i) const {
while (x < 0 || x >= width) { return {x * i, y * i};
if (x < 0) { }
x = -x;
} else if (x >= width) { Vector bounceInBox(uint8_t width, uint8_t height) const {
x = 2 * width - x; double x2 = this->x;
double y2 = this->y;
while (x2 < 0 || x2 >= width) {
if (x2 < 0) {
x2 = -x2;
} else if (x2 >= width) {
x2 = 2 * width - x2;
} }
} }
while (y < 0 || y >= height) { while (y2 < 0 || y2 >= height) {
if (y < 0) { if (y2 < 0) {
y = -y; y2 = -y2;
} else if (y >= height) { } else if (y2 >= height) {
y = 2 * height - y; y2 = 2 * height - y2;
} }
} }
return this; return {x2, y2};
} }
}; };
#endif #endif

View File

@ -6,6 +6,7 @@
#include "mode/Pong/Pong.h" #include "mode/Pong/Pong.h"
#include "mode/SpaceInvaders/SpaceInvaders.h" #include "mode/SpaceInvaders/SpaceInvaders.h"
#include "mode/NewYear/NewYear.h" #include "mode/NewYear/NewYear.h"
#include "mode/Starfield/Starfield.h"
#include "display.h" #include "display.h"
ModeId currentModeId = NONE; ModeId currentModeId = NONE;
@ -85,6 +86,9 @@ void loadNewMode() {
case NEW_YEAR: case NEW_YEAR:
mode = new NewYear(&display); mode = new NewYear(&display);
break; break;
case STARFIELD:
mode = new Starfield(&display);
break;
default: default:
Serial.print("No mode loaded.\n"); Serial.print("No mode loaded.\n");
display.clear(); display.clear();

View File

@ -19,6 +19,7 @@ enum ModeId {
PONG, PONG,
SPACE_INVADERS, SPACE_INVADERS,
NEW_YEAR, NEW_YEAR,
STARFIELD,
}; };
template<typename T> template<typename T>

View File

@ -13,7 +13,7 @@ class Firework {
Display *display{}; Display *display{};
Color color; Color color = MAGENTA;
State state = RISE; State state = RISE;
@ -37,7 +37,7 @@ public:
} }
void reset() { void reset() {
position.set((double) random(display->width), display->height); position = Vector((double) random(display->width), display->height);
color = randomColor(); color = randomColor();
state = INITIAL; state = INITIAL;
@ -93,38 +93,37 @@ public:
} }
void draw() { void draw() {
Vector p;
switch (state) { switch (state) {
case INITIAL: case INITIAL:
break; break;
case RISE: case RISE:
display->set(&position, YELLOW); display->set(position, YELLOW);
break; break;
case EXPLODE: case EXPLODE:
drawParticle(p, +0.0, +1.0); drawParticle(+0.0, +1.0);
drawParticle(p, +0.7, +0.7); drawParticle(+0.7, +0.7);
drawParticle(p, +1.0, +0.0); drawParticle(+1.0, +0.0);
drawParticle(p, +0.7, -0.7); drawParticle(+0.7, -0.7);
drawParticle(p, +0.0, -1.0); drawParticle(+0.0, -1.0);
drawParticle(p, -0.7, -0.7); drawParticle(-0.7, -0.7);
drawParticle(p, -1.0, +0.0); drawParticle(-1.0, +0.0);
drawParticle(p, -0.7, +0.7); drawParticle(-0.7, +0.7);
break; break;
case SPARKLE: case SPARKLE:
if (randomBool(2)) drawParticle(p, +0.0, +1.0); if (randomBool(2)) drawParticle(+0.0, +1.0);
if (randomBool(2)) drawParticle(p, +0.7, +0.7); if (randomBool(2)) drawParticle(+0.7, +0.7);
if (randomBool(2)) drawParticle(p, +1.0, +0.0); if (randomBool(2)) drawParticle(+1.0, +0.0);
if (randomBool(2)) drawParticle(p, +0.7, -0.7); if (randomBool(2)) drawParticle(+0.7, -0.7);
if (randomBool(2)) drawParticle(p, +0.0, -1.0); if (randomBool(2)) drawParticle(+0.0, -1.0);
if (randomBool(2)) drawParticle(p, -0.7, -0.7); if (randomBool(2)) drawParticle(-0.7, -0.7);
if (randomBool(2)) drawParticle(p, -1.0, +0.0); if (randomBool(2)) drawParticle(-1.0, +0.0);
if (randomBool(2)) drawParticle(p, -0.7, +0.7); if (randomBool(2)) drawParticle(-0.7, +0.7);
break; break;
} }
} }
void drawParticle(Vector &p, double x, double y) { void drawParticle(double x, double y) {
display->set(p.set(position)->add(x * explosion, y * explosion), color); display->set(position.plus(x * explosion, y * explosion), color);
} }
bool isAlive() { bool isAlive() {

View File

@ -43,7 +43,7 @@ private:
} }
break; break;
case PLAY: case PLAY:
position.add(velocity); position = position.plus(velocity);
player0.randomMove(display->height); player0.randomMove(display->height);
player1.randomMove(display->height); player1.randomMove(display->height);
paddleBounce(); paddleBounce();
@ -63,7 +63,7 @@ private:
} }
void topBottomBounce() { void topBottomBounce() {
position.bounceInBox(display->width, display->height); position = position.bounceInBox(display->width, display->height);
} }
void checkScoring() { void checkScoring() {
@ -132,7 +132,7 @@ public:
explicit Pong(Display *display) : explicit Pong(Display *display) :
Mode(display), Mode(display),
position(display->width / 2.0, display->height / 2.0), position(display->width / 2.0, display->height / 2.0),
velocity(random(360), exp10(1)) { velocity(Vector::polar(random(360), exp10(1))) {
instance = this; instance = this;
createTimer(100, [](Timer *timer, uint32_t counter, uint32_t currentCount) { instance->tick(timer, counter, currentCount); }); createTimer(100, [](Timer *timer, uint32_t counter, uint32_t currentCount) { instance->tick(timer, counter, currentCount); });
spawnBall(random(2) == 0 ? -1 : +1); spawnBall(random(2) == 0 ? -1 : +1);

View File

@ -0,0 +1,46 @@
#ifndef MEDIATABLE_STARFIELD_H
#define MEDIATABLE_STARFIELD_H
#include "mode/Mode.h"
#define STAR_COUNT 20
class Starfield : public Mode<Starfield> {
private:
Vector center;
Vector stars[STAR_COUNT];
public:
explicit Starfield(Display *display) :
Mode(display),
center(display->width / 2.0, display->height / 2.0) {
for (auto &star: stars) {
star.x = random(display->width);
star.y = random(display->height);
}
}
const char *getName() override {
return "Starfield";
}
void doStep(microseconds_t dt) override {
display->clear();
for (auto &star: stars) {
const Vector velocity = star.minus(center).multiply((double) dt / 200000.0);
star = star.plus(velocity);
if (star.x < 0 || star.x >= display->width || star.y < 0 || star.y >= display->height) {
star = center.plus(Vector::polar(random(360), 1));
}
uint8_t brightness = (uint8_t) round(255.0 * star.minus(center).length / (display->width / 2.0));
display->set(star, gray(brightness));
}
}
};
#endif

View File

@ -59,6 +59,7 @@ void web_index() {
server.sendContent(R"(<a href="/mode?mode=7">PONG</a><br>)"); server.sendContent(R"(<a href="/mode?mode=7">PONG</a><br>)");
server.sendContent(R"(<a href="/mode?mode=8">SPACE_INVADERS</a><br>)"); server.sendContent(R"(<a href="/mode?mode=8">SPACE_INVADERS</a><br>)");
server.sendContent(R"(<a href="/mode?mode=9">NEW_YEAR</a><br>)"); server.sendContent(R"(<a href="/mode?mode=9">NEW_YEAR</a><br>)");
server.sendContent(R"(<a href="/mode?mode=10">STARFIELD</a><br>)");
server.sendContent(R"(Helligkeit: <a href="/brighter">+</a> / <a href="/darker">-</a><br>)"); server.sendContent(R"(Helligkeit: <a href="/brighter">+</a> / <a href="/darker">-</a><br>)");
server.sendContent(R"(Geschwindigkeit: <a href="/faster">+</a> / <a href="/slower">-</a><br>)"); server.sendContent(R"(Geschwindigkeit: <a href="/faster">+</a> / <a href="/slower">-</a><br>)");