aboutsummaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authormrcodetastic <12006953+mrcodetastic@users.noreply.github.com>2024-08-07 19:16:13 +0100
committermrcodetastic <12006953+mrcodetastic@users.noreply.github.com>2024-08-07 19:16:13 +0100
commitad3337b3a32f600c5aa8fda80805dc4f0abe7412 (patch)
treeac18b5dcb6562eb52eacfafd4f9d3fc4402aa80c /examples
parent27a319157dc4c985e5b60ac4680eb320de4240cd (diff)
Add some more patterns
Diffstat (limited to 'examples')
-rw-r--r--examples/AuroraDemo/PatternFireworks.hpp235
-rw-r--r--examples/AuroraDemo/PatternGreenScroll.hpp (renamed from examples/AuroraDemo/PatternTheMatrix.hpp)1
-rw-r--r--examples/AuroraDemo/PatternRain.hpp93
-rw-r--r--examples/AuroraDemo/PatternSphereSpin.hpp103
-rw-r--r--examples/AuroraDemo/PatternStarfield.hpp156
-rw-r--r--examples/AuroraDemo/PatternTunnel.hpp66
-rw-r--r--examples/AuroraDemo/Patterns.hpp21
7 files changed, 445 insertions, 230 deletions
diff --git a/examples/AuroraDemo/PatternFireworks.hpp b/examples/AuroraDemo/PatternFireworks.hpp
new file mode 100644
index 0000000..8d9c13b
--- /dev/null
+++ b/examples/AuroraDemo/PatternFireworks.hpp
@@ -0,0 +1,235 @@
+#ifndef FireWork_H
+#define FireWork_H
+
+/****************************************************************
+ * Fireworks Class
+ ****************************************************************/
+// Ripped from: https://github.com/lmirel/MorphingClockRemix
+
+const int FIREWORKS = 4; // Number of fireworks
+const int FIREWORK_PARTICLES = 32; // Number of particles per firework
+
+const float GRAVITY = 0.03f;
+const float baselineSpeed = -1.2f;
+const float maxSpeed = -2.0f;
+
+class Firework
+{
+ public:
+ float x[FIREWORK_PARTICLES];
+ float y[FIREWORK_PARTICLES];
+ char lx[FIREWORK_PARTICLES], ly[FIREWORK_PARTICLES];
+ float xSpeed[FIREWORK_PARTICLES];
+ float ySpeed[FIREWORK_PARTICLES];
+
+ char red;
+ char blue;
+ char green;
+ char alpha;
+
+ int framesUntilLaunch;
+
+ char particleSize;
+ bool hasExploded;
+
+ Firework(); // Constructor declaration
+ void initialise();
+ void move();
+ void explode();
+};
+
+// Constructor implementation
+Firework::Firework()
+{
+ initialise();
+ for (int loop = 0; loop < FIREWORK_PARTICLES; loop++)
+ {
+ lx[loop] = 0;
+ ly[loop] = VPANEL_H + 1; // Push the particle location down off the bottom of the screen
+ }
+}
+
+void Firework::initialise()
+{
+ // Pick an initial x location and random x/y speeds
+ float xLoc = (rand() % VPANEL_W);
+ float xSpeedVal = baselineSpeed + (rand() % (int)maxSpeed);
+ float ySpeedVal = baselineSpeed + (rand() % (int)maxSpeed);
+
+ // Set initial x/y location and speeds
+ for (int loop = 0; loop < FIREWORK_PARTICLES; loop++)
+ {
+ x[loop] = xLoc;
+ y[loop] = VPANEL_H + 1; // Push the particle location down off the bottom of the screen
+ xSpeed[loop] = xSpeedVal;
+ ySpeed[loop] = ySpeedVal;
+ //don't reset these otherwise particles won't be removed
+ //lx[loop] = 0;
+ //ly[loop] = LAYER_HEIGHT + 1; // Push the particle location down off the bottom of the screen
+ }
+
+ // Assign a random colour and full alpha (i.e. particle is completely opaque)
+ red = (rand() % 255);/// (float)RAND_MAX);
+ green = (rand() % 255); /// (float)RAND_MAX);
+ blue = (rand() % 255); /// (float)RAND_MAX);
+ alpha = 50;//max particle frames
+
+ // Firework will launch after a random amount of frames between 0 and 400
+ framesUntilLaunch = ((int)rand() % (VPANEL_H));
+
+ // Size of the particle (as thrown to glPointSize) - range is 1.0f to 4.0f
+ particleSize = 1.0f + ((float)rand() / (float)RAND_MAX) * 3.0f;
+
+ // Flag to keep trackof whether the firework has exploded or not
+ hasExploded = false;
+
+ //cout << "Initialised a firework." << endl;
+}
+
+void Firework::move()
+{
+ for (int loop = 0; loop < FIREWORK_PARTICLES; loop++)
+ {
+ // Once the firework is ready to launch start moving the particles
+ if (framesUntilLaunch <= 0)
+ {
+ //draw black on last known position
+ //tl->drawPixel (x[loop], y[loop], cc_blk);
+ lx[loop] = x[loop];
+ ly[loop] = y[loop];
+ //
+ x[loop] += xSpeed[loop];
+
+ y[loop] += ySpeed[loop];
+
+ ySpeed[loop] += GRAVITY;
+ }
+ }
+ framesUntilLaunch--;
+
+ // Once a fireworks speed turns positive (i.e. at top of arc) - blow it up!
+ if (ySpeed[0] > 0.0f)
+ {
+ for (int loop2 = 0; loop2 < FIREWORK_PARTICLES; loop2++)
+ {
+ // Set a random x and y speed beteen -4 and + 4
+ xSpeed[loop2] = -2 + (rand() / (float)RAND_MAX) * 4;
+ ySpeed[loop2] = -2 + (rand() / (float)RAND_MAX) * 4;
+ }
+
+ //cout << "Boom!" << endl;
+ hasExploded = true;
+ }
+}
+
+void Firework::explode()
+{
+ for (int loop = 0; loop < FIREWORK_PARTICLES; loop++)
+ {
+ // Dampen the horizontal speed by 1% per frame
+ xSpeed[loop] *= 0.99;
+
+ //draw black on last known position (NO LONGER USED tl->dim used instead)
+ //tl->drawPixel (x[loop], y[loop], cc_blk);
+ lx[loop] = x[loop];
+ ly[loop] = y[loop];
+ //
+ // Move the particle
+ x[loop] += xSpeed[loop];
+ y[loop] += ySpeed[loop];
+
+ // Apply gravity to the particle's speed
+ ySpeed[loop] += GRAVITY;
+ }
+
+ // Fade out the particles (alpha is stored per firework, not per particle)
+ if (alpha > 0)
+ {
+ alpha -= 1;
+ }
+ else // Once the alpha hits zero reset the firework
+ {
+ initialise();
+ }
+}
+
+/*********************** */
+
+
+
+class PatternFirework : public Drawable {
+
+ public:
+ PatternFirework() {
+ name = (char *)"PatternFirework";
+
+ }
+
+ void start();
+ unsigned int drawFrame();
+ void stop();
+
+ private:
+ // Create our array of fireworks
+ Firework fw[FIREWORKS];
+
+};
+
+
+void PatternFirework::start() { }
+
+void PatternFirework::stop() { }
+
+unsigned int PatternFirework::drawFrame()
+{
+
+ effects.DimAll(250);
+
+ CRGB cc_frw;
+ //display.fillScreen (0);
+ // Draw fireworks
+ //cout << "Firework count is: " << Firework::fireworkCount << endl;
+ for (int loop = 0; loop < FIREWORKS; loop++)
+ {
+ for (int particleLoop = 0; particleLoop < FIREWORK_PARTICLES; particleLoop++)
+ {
+
+ // Set colour to yellow on way up, then whatever colour firework should be when exploded
+ if (fw[loop].hasExploded == false)
+ {
+ //glColor4f(1.0f, 1.0f, 0.0f, 1.0f);
+ cc_frw = CRGB (255, 255, 0);
+ }
+ else
+ {
+ //glColor4f(fw[loop].red, fw[loop].green, fw[loop].blue, fw[loop].alpha);
+ //glVertex2f(fw[loop].x[particleLoop], fw[loop].y[particleLoop]);
+ cc_frw = CRGB (fw[loop].red, fw[loop].green, fw[loop].blue);
+ }
+
+ // Draw the point
+ //glVertex2f(fw[loop].x[particleLoop], fw[loop].y[particleLoop]);
+ effects.setPixel (fw[loop].x[particleLoop], fw[loop].y[particleLoop], cc_frw);
+ // effects.setPixel (fw[loop].lx[particleLoop], fw[loop].ly[particleLoop], 0);
+ }
+ // Move the firework appropriately depending on its explosion state
+ if (fw[loop].hasExploded == false)
+ {
+ fw[loop].move();
+ }
+ else
+ {
+ fw[loop].explode();
+ }
+ //
+ //delay (10);
+ } // end loop
+
+ effects.ShowFrame();
+
+ return 20;
+
+} // end drawframe
+
+
+#endif \ No newline at end of file
diff --git a/examples/AuroraDemo/PatternTheMatrix.hpp b/examples/AuroraDemo/PatternGreenScroll.hpp
index ee6aa06..32d38bc 100644
--- a/examples/AuroraDemo/PatternTheMatrix.hpp
+++ b/examples/AuroraDemo/PatternGreenScroll.hpp
@@ -1,5 +1,6 @@
// Codetastic 2024
// ChatGPT was used to create this.
+// It sucks.
#ifndef PatternTheMatrix_H
#define PatternTheMatrix_H
diff --git a/examples/AuroraDemo/PatternRain.hpp b/examples/AuroraDemo/PatternRain.hpp
new file mode 100644
index 0000000..19c34ef
--- /dev/null
+++ b/examples/AuroraDemo/PatternRain.hpp
@@ -0,0 +1,93 @@
+#ifndef PatternRain_H
+#define PatternRain_H
+
+// Codetastic 2024
+
+struct rainDrop {
+ uint8_t x;
+ uint8_t y;
+ CRGB colour;
+};
+
+#define MAX_RAINDROPS 128
+
+class PatternRain : public Drawable {
+
+ public:
+ PatternRain()
+ {
+ name = (char *)"PatternRain";
+ }
+
+ void start() {
+
+ buffer = (uint16_t *) malloc(((VPANEL_W*VPANEL_H)+1)*sizeof(uint16_t)); // always alloc an extra amount for XY
+ }
+
+ void stop() {
+
+ free(buffer);
+
+ }
+
+
+ unsigned int drawFrame()
+ {
+ rain(32, 255, 224, 240, CRGB::Green);
+
+ effects.ShowFrame();
+
+ return 45; // 1000/45 frames per secton
+
+ }
+
+
+
+ private:
+
+ struct rainDrop rainDrops[MAX_RAINDROPS];
+ int rainDropPos = 0;
+
+ uint16_t* buffer = NULL; // buffer of number
+
+ void rain(byte backgroundDepth, byte maxBrightness, byte spawnFreq, byte tailLength, CRGB rainColor)
+ {
+ CRGBPalette16 rain_p( CRGB::Black, rainColor );
+
+ // Dim routine
+ for (int16_t i = 0; i < VPANEL_W; i++) {
+ for (int16_t j = 0; j < VPANEL_H; j++) {
+ uint16_t xy = XY16(i, j);
+ effects.leds[xy].nscale8(tailLength);
+ }
+ }
+
+ // Genrate a new raindrop if the randomness says we should
+ if (random(255) < spawnFreq) {
+
+ // Find a spare raindrop slot
+ for (int d = 0; d < MAX_RAINDROPS; d++) {
+
+ // This raindrop is done with, it has... dropped
+ if (rainDrops[d].y >= VPANEL_H ) // not currently in use
+ {
+ rainDrops[d].colour = ColorFromPalette(rain_p, random(backgroundDepth, maxBrightness));
+ rainDrops[d].x = random(VPANEL_W-1);
+ rainDrops[d].y = 0;
+
+ break; // exit until next time.
+ }
+ }
+ } // end random spawn
+
+ // Iterate through all the rainDrops, draw the drop pixel on the layer
+ for (int d = 0; d < MAX_RAINDROPS; d++) {
+ effects.setPixel(rainDrops[d].x, rainDrops[d].y++, rainDrops[d].colour);
+ }
+
+ }
+
+
+};
+
+#endif \ No newline at end of file
diff --git a/examples/AuroraDemo/PatternSphereSpin.hpp b/examples/AuroraDemo/PatternSphereSpin.hpp
deleted file mode 100644
index 7da2537..0000000
--- a/examples/AuroraDemo/PatternSphereSpin.hpp
+++ /dev/null
@@ -1,103 +0,0 @@
-// Codetastic 2024
-// ChatGPT was used to create this.
-
-#ifndef PatternSphereSpin_H
-#define PatternSphereSpin_H
-
-#include <vector>
-#include <cmath>
-
-struct Point3D {
- float x, y, z;
-};
-
-struct Point2D {
- int x, y;
-};
-
-class PatternSphereSpin : public Drawable {
-
- private:
-
- std::vector<Point3D> points;
-
- float angleX = 0.0f;
- float angleY = 0.0f;
- float distance = 3.0f;
-
-
- Point2D project(Point3D point, float distance) {
- Point2D projected;
- projected.x = static_cast<int>((point.x / (distance - point.z)) * VPANEL_W / 2 + VPANEL_W / 2);
- projected.y = static_cast<int>((point.y / (distance - point.z)) * VPANEL_H / 2 + VPANEL_H / 2);
- return projected;
- }
-
- std::vector<Point3D> generateSpherePoints(int numPoints) {
- std::vector<Point3D> points;
- for (int i = 0; i < numPoints; ++i) {
- float theta = 2 * PI * (i / static_cast<float>(numPoints));
- for (int j = 0; j < numPoints / 2; ++j) {
- float phi = PI * (j / static_cast<float>(numPoints / 2));
- points.push_back({ cos(theta) * sin(phi), sin(theta) * sin(phi), cos(phi) });
- }
- }
- return points;
- }
-
- void rotatePoints(std::vector<Point3D>& points, float angleX, float angleY) {
- for (auto& point : points) {
- // Rotate around the X axis
- float y = point.y * cos(angleX) - point.z * sin(angleX);
- float z = point.y * sin(angleX) + point.z * cos(angleX);
- point.y = y;
- point.z = z;
-
- // Rotate around the Y axis
- float x = point.x * cos(angleY) + point.z * sin(angleY);
- z = -point.x * sin(angleY) + point.z * cos(angleY);
- point.x = x;
- point.z = z;
- }
- }
-
-
- public:
- PatternSphereSpin() {
- name = (char *)"Sphere Spin";
- }
-
- void start()
- {
- points = generateSpherePoints(30);
- angleX = 0.0f;
- angleY = 0.0f;
- distance = 3.0f;
- };
-
- unsigned int drawFrame() {
-
- effects.ClearFrame();
-
- // Rotate points
- rotatePoints(points, angleX, angleY);
-
- // Project and draw lines between points
- for (size_t i = 0; i < points.size(); ++i) {
- Point2D p1 = project(points[i], distance);
- for (size_t j = i + 1; j < points.size(); ++j) {
- Point2D p2 = project(points[j], distance);
- effects.drawLine(p1.x, p1.y, p2.x, p2.y, CRGB(255,255,255));
- }
- }
-
- // Update angles for rotation
- angleX += 0.05f;
- angleY += 0.05f;
-
- effects.ShowFrame();
- return 0;
- }
-};
-
-#endif
diff --git a/examples/AuroraDemo/PatternStarfield.hpp b/examples/AuroraDemo/PatternStarfield.hpp
index 2c637fb..52253fb 100644
--- a/examples/AuroraDemo/PatternStarfield.hpp
+++ b/examples/AuroraDemo/PatternStarfield.hpp
@@ -1,77 +1,133 @@
-// Codetastic 2024
-// ChatGPT was used to create this.
-
#ifndef PatternStarfield_H
#define PatternStarfield_H
-#include <vector>
-
-#define STAR_COUNT 128
+struct Star
+{
+ Star() {
+ x = y = z = 0;
+ colour = CRGB::White;
+ }
-// Star structure
-struct Star {
- float x, y, z;
- CRGB colour;
+ float x;
+ float y;
+ float z;
+ CRGB colour;
};
-
+// Based on https://github.com/sinoia/oled-starfield/blob/master/src/starfield.cpp
class PatternStarfield : public Drawable {
private:
- std::vector<Star> stars;
- float speed = 0.5f;
+ const int starCount = 100; // number of stars in the star field
+ const int maxDepth = 32; // maximum distance away for a star
- public:
- PatternStarfield() {
- name = (char *)"Starfield";
- }
+ // the star field - starCount stars represented as x, y and z co-ordinates
+ // https://www.cplusplus.com/doc/tutorial/dynamic/
+ Star * stars;
+ //CRGBPalette16 currentPalette;
- void start()
- {
+ unsigned int drawFrame() { // aka drawStars
- stars.resize(STAR_COUNT);
+ // Dim routine
+
+ for (int16_t i = 0; i < VPANEL_W; i++) {
+ for (int16_t j = 0; j < VPANEL_H; j++) {
- for (int i = 0; i < STAR_COUNT; ++i) {
- stars[i] = { static_cast<float>(rand() % VPANEL_W - VPANEL_W / 2),
- static_cast<float>(rand() % VPANEL_H - VPANEL_H / 2),
- static_cast<float>(rand() % VPANEL_W),
- effects.ColorFromCurrentPalette(rand()*255)
- };
- } // random positions
- };
+ uint16_t xy = XY16(i, j);
+ effects.leds[xy].nscale8(250);
+ }
+ }
- unsigned int drawFrame() {
+ int origin_x = VPANEL_W / 2;
+ int origin_y = VPANEL_H / 2;
- effects.DimAll(250);
+ // Iterate through the stars reducing the z co-ordinate in order to move the
+ // star closer.
+ for (int i = 0; i < starCount; ++i) {
+ stars[i].z -= 0.1;
+ // if the star has moved past the screen (z < 0) reposition it far away
+ // with random x and y positions.
+ if (stars[i].z <= 0)
+ {
+ stars[i].x = getRandom(-25, 25);
+ stars[i].y = getRandom(-25, 25);
+ stars[i].z = maxDepth;
+ }
+
+ // Convert the 3D coordinates to 2D using perspective projection.
+ float k = VPANEL_W / stars[i].z;
+ int x = static_cast<int>(stars[i].x * k + origin_x);
+ int y = static_cast<int>(stars[i].y * k + origin_y);
+
+ // Draw the star (if it is visible in the screen).
+ // Distant stars are smaller than closer stars.
+ if ((0 <= x and x < VPANEL_H)
+ and (0 <= y and y < VPANEL_H)) {
- // Update star positions
- for (auto& star : stars) {
- star.z -= speed;
- if (star.z <= 0) {
- star.z = VPANEL_W;
- star.x = static_cast<float>(rand() % VPANEL_W - VPANEL_W / 2);
- star.y = static_cast<float>(rand() % VPANEL_H - VPANEL_H / 2);
+ CRGB tmp = stars[i].colour;
+ //CRGB tmp = CRGB::White;
+ byte scale = 255 -(stars[i].z*7);
+ tmp.nscale8(scale);
+
+ effects.setPixel(x,y, CRGB(tmp.r,tmp.g,tmp.b));
+ }
+ else
+ {
+ stars[i].z = -1; // set to -1 so it gets re-popualted
}
}
- // draw position
- for (const auto& star : stars) {
- float k = 128.0f / star.z;
- int x = static_cast<int>(star.x * k + VPANEL_W / 2);
- int y = static_cast<int>(star.y * k + VPANEL_H / 2);
+ effects.ShowFrame();
+
+ return 5;
+ }
+
+ int getRandom(int lower, int upper) {
+ /* Generate and return a random number between lower and upper bound */
+ return lower + static_cast<int>(rand() % (upper - lower + 1));
+ }
+
+/*
+ CRGB ColorFromCurrentPalette(uint8_t index = 0, uint8_t brightness = 255, TBlendType blendType = LINEARBLEND) {
+ return ColorFromPalette(currentPalette, index, brightness, blendType);
+ }
+*/
+
+ public:
+ PatternStarfield()
+ {
+ name = (char *)"PatternStarfield";
+ }
- if (x >= 0 && x < VPANEL_W && y >= 0 && y < VPANEL_H) {
+ void start() {
+
+ //currentPalette = RainbowColors_p;
+ //currentPalette = CloudColors_p;
- // TODO: Get brighter as we get closer to edges?
- effects.setPixel(x, y, star.colour);
- }
- }
+ // Allocate memory
+ stars = new Star[starCount];
- effects.ShowFrame();
- return 0;
+ // Initialise the star field with random stars
+ for (int i = 0; i < starCount; i++) {
+ stars[i].x = getRandom(-25, 25);
+ stars[i].y = getRandom(-25, 25);
+ stars[i].z = getRandom(0, maxDepth);
+ //stars[i].colour = ColorFromCurrentPalette(random(0, 128));
+ stars[i].colour = effects.ColorFromCurrentPalette(random(0, 128));
+ }
+ } // end start
+
+ void stop() {
+
+ delete[] stars;
+ delete stars;
+
}
+
+
+
};
-#endif
+#endif \ No newline at end of file
diff --git a/examples/AuroraDemo/PatternTunnel.hpp b/examples/AuroraDemo/PatternTunnel.hpp
deleted file mode 100644
index 89859ae..0000000
--- a/examples/AuroraDemo/PatternTunnel.hpp
+++ /dev/null
@@ -1,66 +0,0 @@
-// Codetastic 2024
-// ChatGPT was used to create this.
-
-#ifndef PatternTunnel_H
-#define PatternTunnel_H
-
-class PatternTunnel : public Drawable {
-
- private:
-
- uint8_t circlePositions[5] = {0, 6, 12, 18, 24}; // Initial positions of circles
-
-
- public:
- PatternTunnel() {
- name = (char *)"Tunnel";
- }
-
-
-
- // Function to draw a circle on the matrix
- void drawCircle(int centerX, int centerY, int radius, CRGB color) {
- for (int y = -radius; y <= radius; y++) {
- for (int x = -radius; x <= radius; x++) {
- if (x*x + y*y <= radius*radius) {
- int drawX = centerX + x;
- int drawY = centerY + y;
- if (drawX >= 0 && drawX < VPANEL_W && drawY >= 0 && drawY < VPANEL_H) {
- effects.leds[XY(drawX, drawY)] = color;
- }
- }
- }
- }
- }
-
- void start()
- {
-
- };
-
- unsigned int drawFrame() {
-
- effects.DimAll(250);
-
-
- // Draw circles
- for (int i = 0; i < 5; i++) {
- int radius = circlePositions[i] % 32;
- CRGB color = CHSV(map(radius, 0, 31, 0, 255), 255, 255);
- drawCircle(VPANEL_W / 2, VPANEL_H / 2, radius, color);
-
- // Move circles forward
- circlePositions[i]++;
-
- // Reset the position if the circle is out of bounds
- if (circlePositions[i] >= 32) {
- circlePositions[i] = 0;
- }
- }
-
- effects.ShowFrame();
- return 0;
- }
-};
-
-#endif
diff --git a/examples/AuroraDemo/Patterns.hpp b/examples/AuroraDemo/Patterns.hpp
index a93d998..cdd8bd5 100644
--- a/examples/AuroraDemo/Patterns.hpp
+++ b/examples/AuroraDemo/Patterns.hpp
@@ -43,17 +43,17 @@
#include "PatternSpiral.hpp"
#include "PatternSpiro.hpp"
#include "PatternWave.hpp"
-#include "PatternTheMatrix.hpp"
+#include "PatternRain.hpp"
#include "PatternJuliaSetFractal.hpp"
-//#include "PatternTunnel.hpp" // fail
-//#include "PatternSphereSpin.hpp" // fail
+#include "PatternRain.hpp"
+#include "PatternFireworks.hpp"
+
class Patterns {
private:
PatternStarfield starfield;
- // PatternSphereSpin sspin;
PatternAttract attract;
PatternBounce bounce;
PatternCube cube;
@@ -74,16 +74,15 @@ class Patterns {
PatternSpiral spiral;
PatternSpiro spiro;
PatternWave wave;
- PatternTheMatrix matrix;
- // PatternTunnel tunnel;
PatternJuliaSet juliaSet;
+
+ PatternRain rain;
+ PatternFirework fireworks;
+
std::vector<Drawable*> availablePatterns = {
- // &tunnel,
&juliaSet,
- &matrix,
&starfield,
- // &sspin,
&attract,
&bounce,
&cube,
@@ -102,10 +101,10 @@ class Patterns {
&plasma,
&radar,
&simpnoise,
- //&snake, // a bit crap
- //&spiral, // a bit crap
&spiro,
&wave,
+ &rain,
+ &fireworks
};
int currentIndex = 0;