initial commit

This commit is contained in:
2026-02-26 22:03:45 +01:00
parent 5ddf968ff1
commit d45427531c
4 changed files with 2292 additions and 0 deletions
+878
View File
@@ -0,0 +1,878 @@
#include "animation.h"
#include <math.h>
#include <pgmspace.h>
#define WIDTH 20
#define HEIGHT 20
#define SIN_TABLE_SIZE 256
#define TWO_PI 6.28318530717958647692f
#define INV_TWO_PI (1.0f / TWO_PI)
const float sinTable[SIN_TABLE_SIZE] PROGMEM = {
#include "sin_table_256.inc"
};
// Pumpkin pixel art 8x8 (simplified)
// 0 = empty, 1 = pumpkin body, 2 = eye
const uint8_t pumpkinSprite[8][8] = {
{0,1,1,1,1,1,1,0},
{1,1,1,1,1,1,1,1},
{1,2,0,1,1,0,2,1},
{1,1,1,1,1,1,1,1},
{1,1,1,0,0,1,1,1},
{1,1,0,1,1,0,1,1},
{0,1,1,1,1,1,1,0},
{0,0,1,1,1,1,0,0}
};
const uint8_t imageManuBude[20][20] = {
{0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0},
{1,1,1,1,1,1,1,1,0,0,0,1,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,1,0,0,0,0,1,1,1,1,1,1,1,1,1},
{0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0},
{1,1,1,1,1,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0},
{0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0},
{1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,1},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
};
// Colors
uint32_t pumpkinColor = Adafruit_NeoPixel::Color(255,140,0); // orange
uint32_t eyeBaseColor = Adafruit_NeoPixel::Color(255,60,0); // fiery red-orange
static inline float sinPreCalc(float value)
{
// Scale factor (precompute once as constant)
const float scale = SIN_TABLE_SIZE / TWO_PI;
// Convert radians → table index (float)
float index = value * scale;
// Convert to integer index
int i0 = (int)index;
// Fractional part for interpolation
float frac = index - i0;
// Wrap index using power-of-two mask (256 -> 0xFF)
i0 &= (SIN_TABLE_SIZE - 1);
int i1 = (i0 + 1) & (SIN_TABLE_SIZE - 1);
// Read from flash
float s0 = pgm_read_float(&sinTable[i0]);
float s1 = pgm_read_float(&sinTable[i1]);
// Linear interpolation
return s0 + frac * (s1 - s0);
}
// Bubble animation function
uint32_t bubbles(uint8_t x, uint8_t y, float timeMs) {
float colorR = 0, colorG = 0, colorB = 0;
// Generate several bubbles per column
for (uint8_t i = 0; i < 5; i++) {
// Each bubble has its own horizontal position and speed
float speed = 0.02f + 0.01f * (hash8(i*3, x)/255.0f); // pixels/ms
float phase = hash8(i*7, x)/255.0f * HEIGHT; // starting row
float bubbleY = fmod((timeMs*speed + phase), HEIGHT);
// Distance from this bubble to pixel
float dist = fabs(bubbleY - y);
if (dist < 1.5) { // bubble radius
// Brightness fades at edges
float brightness = 1.0f - (dist/1.5f);
colorR += 100 * brightness;
colorG += 180 * brightness;
colorB += 255 * brightness;
}
}
// Clamp colors
if (colorR > 255) colorR = 255;
if (colorG > 255) colorG = 255;
if (colorB > 255) colorB = 255;
return Adafruit_NeoPixel::Color((uint8_t)colorR, (uint8_t)colorG, (uint8_t)colorB);
}
// Pseudo-random flicker
float flicker(float timeMs, uint8_t seed) {
return 0.6f + 0.4f * sinPreCalc(timeMs*0.01f + seed*3.14f); // 0.6..1.0
}
// Pumpkin pixel function
uint32_t minecraftPumpkin(uint8_t x, uint8_t y, float timeMs) {
int spriteWidth = 8;
int spriteHeight = 8;
int offsetX = WIDTH/2 - spriteWidth/2;
int offsetY = HEIGHT/2 - spriteHeight/2;
int localX = x - offsetX;
int localY = y - offsetY;
if (localX >= 0 && localX < spriteWidth && localY >= 0 && localY < spriteHeight) {
uint8_t val = pumpkinSprite[localY][localX];
if (val == 1) return pumpkinColor;
if (val == 2) {
// Flickering fire eyes
float f = flicker(timeMs, localX*10 + localY);
uint8_t r = (uint8_t)(255 * f);
uint8_t g = (uint8_t)(60 * f);
uint8_t b = 0;
return Adafruit_NeoPixel::Color(r,g,b);
}
}
return Adafruit_NeoPixel::Color(0,0,0); // background black
}
// Among Us pixel art 7x7 (simplified)
// 0 = empty, 1 = body, 2 = visor
const uint8_t amongUsSprite[8][8] = {
{0,0,1,1,1,1,0,0},
{0,1,1,3,3,3,3,0},
{1,1,3,2,2,2,2,3},
{1,1,3,2,2,2,2,3},
{1,1,1,3,3,3,3,0},
{1,1,1,1,1,1,1,0},
{0,1,1,1,1,1,1,0},
{0,1,1,0,0,1,1,0}
};
// Colors
uint32_t bodyColor = Adafruit_NeoPixel::Color(255,0,0); // red crewmate
uint32_t visorColor = Adafruit_NeoPixel::Color(150,200,255); // visor
uint32_t visorColorInner = Adafruit_NeoPixel::Color(0,0,255); // visor
// Function to get pixel color of Among Us crewmate
uint32_t amongUsPixel(uint8_t x, uint8_t y, float timeMs) {
// Move crewmate horizontally across screen
int spriteWidth = 8;
int spriteHeight = 8;
int posX = (int)(fmod(timeMs * 0.01f, WIDTH + spriteWidth)) - spriteWidth;
int posY = HEIGHT / 2 - spriteHeight / 2;
int localX = x - posX;
int localY = y - posY;
if (localX >= 0 && localX < spriteWidth && localY >= 0 && localY < spriteHeight) {
uint8_t val = amongUsSprite[localY][localX];
if (val == 1) return bodyColor;
if (val == 2) return visorColorInner;
if (val == 3) return visorColor;
}
return Adafruit_NeoPixel::Color(0,0,0); // background black
}
// Fast pseudo-random hash function (per pixel)
uint8_t hash8(uint16_t x, uint16_t y) {
uint32_t h = x * 374761393 + y * 668265263; // large primes
h = (h ^ (h >> 13)) * 1274126177;
return (h >> 16) & 0xFF;
}
// Purple rain waterfall color function
uint32_t purpleRain(uint8_t x, uint8_t y, float timeMs) {
// Each column has its own speed
float speed = 0.03f + 0.01f * (hash8(x, 0) / 255.0f); // pixels/ms
float t = timeMs * speed;
// Determine the head of the falling stream
int headRow = (int)t % HEIGHT;
// Distance from head
int dist = (y + HEIGHT - headRow) % HEIGHT;
// Brightness fades with distance
uint8_t brightness = 0;
if (dist == 0) brightness = 255; // brightest head
else if (dist < 6) brightness = 255 - dist * 60; // fading tail
else brightness = 0;
// Purple color: R and B nonzero, G low
uint8_t r = brightness;
uint8_t g = brightness / 2; // small green tint
uint8_t b = brightness;
return Adafruit_NeoPixel::Color(r, g, b);
}
// Starry sky function
uint32_t starrySky(uint8_t x, uint8_t y, float timeMs) {
uint8_t seed = hash8(x, y);
// Only ~5% of pixels have stars
if (seed < 20) { // 0..12
// Twinkle: small brightness variation
float phase = (timeMs * 0.002f + seed) * 0.1f;
float blink = 0.7f + 0.8f * sinPreCalc(phase * 6.2831f); // 0.4..1.0
uint8_t brightness = (uint8_t)(150 * blink + 50); // 50..200
return Adafruit_NeoPixel::Color(brightness, brightness, brightness);
}
// Shooting star: rare (~0.5%) moving diagonally
float t = fmod(timeMs * 0.01f, WIDTH + HEIGHT);
if (seed > 250 && fabs(x - t) < 1 && fabs(y - t) < 1) {
return Adafruit_NeoPixel::Color(255, 200, 150);
}
// Otherwise empty sky
return Adafruit_NeoPixel::Color(0, 0, 0);
}
uint32_t spinningDavidStarPixel(uint8_t x, uint8_t y, float timeMs) {
float t = timeMs * 0.001f; // seconds
// Center of the matrix
float cx = 10.0f;
float cy = 10.0f;
// Translate to center
float dx = x - cx;
float dy = y - cy;
// Rotation angle
float angle = t * 2.0f; // radians, spins over time
float cosA = sinPreCalc(TWO_PI/4 - angle);
float sinA = sinPreCalc(angle);
float rx = dx * cosA - dy * sinA;
float ry = dx * sinA + dy * cosA;
// Star of David = two overlapping equilateral triangles
// Approximate with slopes: y = ±sqrt(3)*x for the triangles
bool inStar = false;
// Upper triangle
if (ry >= -rx * 1.7f && ry >= rx * 1.7f && ry <= 0) inStar = true;
// Lower triangle
if (ry <= -rx * 1.7f && ry <= rx * 1.7f && ry >= 0) inStar = true;
// Draw the star
if (inStar) {
// Optional: pulsating color
uint8_t pulse = 150 + 105 * sinPreCalc(t * 3.0f);
return NeoPixel.Color(pulse, pulse, 255);
}
// Background
return NeoPixel.Color(0, 0, 20);
}
uint32_t jumpingJackPixel(uint8_t x, uint8_t y, float timeMs) {
float t = timeMs * 0.001f; // seconds
// Center of the stick figure
int cx = 10;
int cy = 12;
// Oscillation amplitudes
float armSpread = 4.0f * sinPreCalc(t * 2.0f); // arms
float legSpread = 4.0f * sinPreCalc(t * 2.0f); // legs
float jump = sinPreCalc(t * 2.0f) * -3.0f; // up/down jump
// Background
uint32_t bg = NeoPixel.Color(0, 0, 0);
// -----------------
// Head (3x3)
// -----------------
int headY = cy - 5 + (int)jump;
if ((x >= cx - 1 && x <= cx + 1) && (y >= headY && y <= headY + 2)) {
return NeoPixel.Color(255, 255, 255);
}
// -----------------
// Body (vertical)
// -----------------
int bodyTop = cy - 2 + (int)jump;
int bodyBottom = cy + 2 + (int)jump;
if (x == cx && y >= bodyTop && y <= bodyBottom) {
return NeoPixel.Color(255, 255, 255);
}
// -----------------
// Arms (diagonal)
// -----------------
int leftArmX = cx - 1 - (int)armSpread;
int rightArmX = cx + 1 + (int)armSpread;
int armY = cy - 1 + (int)jump;
if ((x == leftArmX && y == armY - 1) || (x == leftArmX + 1 && y == armY) ||
(x == rightArmX && y == armY - 1) || (x == rightArmX - 1 && y == armY)) {
return NeoPixel.Color(255, 255, 255);
}
// -----------------
// Legs (diagonal)
// -----------------
int leftLegX = cx - 1 - (int)legSpread;
int rightLegX = cx + 1 + (int)legSpread;
int legY = cy + 3 + (int)jump;
if ((x == leftLegX && y == legY) || (x == leftLegX + 1 && y == legY + 1) ||
(x == rightLegX && y == legY) || (x == rightLegX - 1 && y == legY + 1)) {
return NeoPixel.Color(255, 255, 255);
}
return bg;
}
uint32_t bonfireMoonPixel(uint8_t x, uint8_t y, float timeMs) {
float t = timeMs * 0.001f; // seconds
// ------------------------
// Quarter moon (crescent)
// ------------------------
int moonX = 15;
int moonY = 4;
int moonR = 3;
float mdx = x - moonX;
float mdy = y - moonY;
float mdist = sqrt(mdx * mdx + mdy * mdy);
bool inMoon = (mdist <= moonR);
// Cut-out circle to form crescent
float cutX = moonX + 2; // shift right to carve shadow
float cdx = x - cutX;
float cdist = sqrt(cdx * cdx + mdy * mdy);
bool inShadow = (cdist <= moonR);
if (inMoon && !inShadow) {
uint8_t glow = 140 + 40 * sinPreCalc(t * 0.5f);
return NeoPixel.Color(glow, glow, glow + 20);
}
// ------------
// Big bonfire
// ------------
int baseX = 10;
int baseY = 16;
bool log1 = (y == baseY && x >= 4 && x <= 15);
bool log2 = (y == baseY - 1 && x >= 5 && x <= 14);
bool log3 = (y == baseY - 2 && x >= 7 && x <= 12);
if (log1 || log2 || log3) {
return NeoPixel.Color(100, 50, 15);
}
int dx = x - baseX;
int dy = baseY - y;
if (dy >= 0 && dy <= 10 && abs(dx) <= (5 - dy / 2)) {
float flicker = sinPreCalc(t * 9.0f + x * 2.1f + y * 1.4f) * 0.5f + 0.5f;
uint8_t r = 170 + 85 * flicker;
uint8_t g = 70 + 160 * flicker - dy * 8;
uint8_t b = 0;
return NeoPixel.Color(constrain(r, 150, 255),
constrain(g, 40, 220),
b);
}
if (dy == 0 && abs(dx) <= 6) {
uint8_t glow = 90 + 50 * sinPreCalc(t * 7.0f + x * 0.8f);
return NeoPixel.Color(glow, glow / 2, 0);
}
// ----------------
// Night sky bg
// ----------------
uint8_t stars = 4 + 6 * sinPreCalc(t * 0.3f + x * 0.6f + y * 0.4f);
return NeoPixel.Color(0, 0, stars);
}
uint32_t nyanCatPixel(uint8_t x, uint8_t y, float timeMs) {
float t = timeMs * 0.0015f; // seconds
// Cat position (flies left -> right, loops)
float catXf = fmod(t * 6.0f, 30.0f) - 6.0f; // offscreen -> onscreen
int catX = (int)catXf;
int catY = 10 + (int)(sinPreCalc(t * 2.0f) * 2.0f);
// Background space
uint8_t stars = 5 + 10 * sinPreCalc(t * 0.7f + x * 0.9f + y * 0.4f);
uint32_t bg = NeoPixel.Color(0, 0, stars);
// Rainbow trail (behind cat)
if (x < catX && x > catX - 8 && abs(y - catY) <= 1) {
float phase = t * 6.0f + x * 0.5f;
uint8_t r = 127 + 127 * sinPreCalc(phase + 0.0f);
uint8_t g = 127 + 127 * sinPreCalc(phase + 2.1f);
uint8_t b = 127 + 127 * sinPreCalc(phase + 4.2f);
return NeoPixel.Color(r, g, b);
}
// Simple cat sprite (5x4)
bool cat =
(x == catX && y == catY) ||
(x == catX + 1 && y == catY) ||
(x == catX + 2 && y == catY) ||
(x == catX + 3 && y == catY) ||
(x == catX && y == catY - 1) ||
(x == catX + 1 && y == catY - 1) ||
(x == catX + 2 && y == catY - 1) ||
(x == catX + 3 && y == catY - 1) ||
(x == catX + 1 && y == catY - 2) ||
(x == catX + 2 && y == catY - 2) ||
(x == catX + 1 && y == catY + 1) ||
(x == catX + 2 && y == catY + 1);
if (cat) {
return NeoPixel.Color(200, 180, 160); // cat body
}
// Face pixels (eyes)
if (x == catX + 1 && y == catY - 1) return NeoPixel.Color(0, 0, 0);
if (x == catX + 2 && y == catY - 1) return NeoPixel.Color(0, 0, 0);
return bg;
}
uint32_t xwingDeathStarPixel(uint8_t x, uint8_t y, float timeMs) {
// Convert ms to seconds for smooth trig
float t = timeMs * 0.001f;
// Scene timing (ms)
float flyTime = 2000.0f;
float shootTime = 1200.0f;
float explodeTime = 2000.0f;
float total = flyTime + shootTime + explodeTime;
float local = fmod(timeMs, total);
// Positions
int xwingX = (int)(-5 + (local / flyTime) * 30); // flies left -> right
int xwingY = 10 + (int)(sinPreCalc(t * 2.0f) * 2.0f);
int dsX = 15;
int dsY = 10;
int dsR = 3;
// Background stars
uint8_t bg = 10 + 10 * sinPreCalc(t * 0.5f + x * 0.7f + y * 0.3f);
uint32_t color = NeoPixel.Color(0, 0, bg);
// Death Star body
float dx = x - dsX;
float dy = y - dsY;
float dist = sqrt(dx * dx + dy * dy);
bool onDeathStar = dist <= dsR;
// Phase 1: Fly-by
if (local < flyTime) {
if (onDeathStar) {
return NeoPixel.Color(120, 120, 120); // gray Death Star
}
}
// Phase 2: Shooting
if (local >= flyTime && local < flyTime + shootTime) {
if (onDeathStar) {
return NeoPixel.Color(150, 150, 150);
}
// Laser beam
int laserY = xwingY;
if (y == laserY && x > xwingX && x < dsX) {
return NeoPixel.Color(255, 0, 0);
}
}
// Phase 3: Explosion
if (local >= flyTime + shootTime) {
float e = local - flyTime - shootTime;
float radius = e * 0.005f;
if (dist < radius) {
uint8_t r = 255;
uint8_t g = max(0, 200 - (int)(e * 0.1f));
uint8_t b = 0;
return NeoPixel.Color(r, g, b);
}
}
// X-Wing sprite (tiny cross)
bool xwing =
(x == xwingX && y == xwingY) ||
(x == xwingX - 1 && y == xwingY) ||
(x == xwingX + 1 && y == xwingY) ||
(x == xwingX && y == xwingY - 1) ||
(x == xwingX && y == xwingY + 1);
if (xwing) {
return NeoPixel.Color(200, 200, 200);
}
return color;
}
uint32_t flappyBirdPixel(uint8_t x, uint8_t y, float t) {
const int W = 20;
const int H = 20;
float time = 0.0;
time = t / 400;
// Bird position (fixed X, smooth Y motion)
int birdX = 5;
float birdY = 10.0f + sinPreCalc(time * 3.0f) * 3.0f; // flap motion
// Pipe movement (smooth scrolling)
float pipePos = 19.0f - fmod(time * 4.0f, 25.0f);
int pipeX = (int)pipePos;
// Moving gap
float gapCenter = 10.0f + sinPreCalc(time * 0.7f) * 4.0f;
int gapSize = 5;
// Background (sky)
uint8_t bgR = 0, bgG = 0, bgB = 20;
// Pipes
bool isPipe = (x == pipeX || x == pipeX - 1);
bool inGap = (y >= gapCenter - gapSize / 2.0f &&
y <= gapCenter + gapSize / 2.0f);
if (isPipe && !inGap) {
return NeoPixel.Color(0, 160, 0);
}
// Bird (2x2)
bool isBird =
(x == birdX || x == birdX + 1) &&
(y == (int)birdY || y == (int)(birdY + 1));
if (isBird) {
return NeoPixel.Color(255, 220, 0);
}
return NeoPixel.Color(bgR, bgG, bgB);
}
uint32_t creeper(uint8_t x, uint8_t y, uint32_t timestep) {
int phase = (timestep / 40) % 120; // animation cycle
int cx = 10;
int cy = 10;
// Base color = off
uint8_t r = 0, g = 0, b = 0;
// Creeper face mask
bool face = false;
bool eyeL = (x >= 5 && x <= 7 && y >= 5 && y <= 7);
bool eyeR = (x >= 12 && x <= 14 && y >= 5 && y <= 7);
bool mouth =
((x >= 7 && x <= 12 && y >= 11 && y <= 13) ||
(x >= 8 && x <= 9 && y >= 9 && y <= 11) ||
(x >= 10 && x <= 11 && y >= 9 && y <= 11));
bool head = (x >= 3 && x <= 16 && y >= 3 && y <= 16);
// Phase 1 Normal creeper
if (phase < 50) {
if (head) {
if (eyeL || eyeR || mouth) {
return NeoPixel.Color(0, 0, 0);
} else {
return NeoPixel.Color(0, 180, 0);
}
}
return NeoPixel.Color(0, 0, 0);
}
// Phase 2 White flash (about to explode)
if (phase < 65) {
if (head) {
uint8_t flash = 200 + 55 * sinPreCalc(phase * 0.8);
return NeoPixel.Color(flash, flash, flash);
}
return NeoPixel.Color(0, 0, 0);
}
// Phase 3 Explosion
int t = phase - 65;
float dx = x - cx;
float dy = y - cy;
float dist = sqrt(dx * dx + dy * dy);
// Expanding explosion radius
float radius = t * 0.4;
if (dist > radius && dist < radius + 2) {
// fiery ring
uint8_t rr = 255;
uint8_t gg = random(80, 160);
return NeoPixel.Color(rr, gg, 0);
}
if (dist < radius) {
// fading embers
uint8_t fade = max(0, 200 - t * 6);
return NeoPixel.Color(fade, fade / 2, 0);
}
return NeoPixel.Color(0, 0, 0);
}
uint32_t breathe(uint8_t x, uint8_t y, float t) {
float cx = 9.5, cy = 9.5;
float dx = x - cx;
float dy = y - cy;
float dist = sqrt(dx * dx + dy * dy);
float wave = sinPreCalc(dist * 0.6 - t * 0.05 / 200.0);
float breath = (sinPreCalc(t * 0.02 / 200.0) + 1) * 0.5;
uint8_t r = 50 + 200 * breath;
uint8_t g = 30 + 100 * wave * breath;
uint8_t b = 150 + 100 * (1 - breath);
return NeoPixel.Color(r, g, b);
}
uint32_t galaxy(uint8_t x, uint8_t y, float t) {
float cx = 9.5, cy = 9.5;
float dx = x - cx;
float dy = y - cy;
float angle = atan2(dy, dx);
float dist = sqrt(dx * dx + dy * dy);
float spin = angle + dist * 0.3 - t / 10 * 0.02;
float v = (sinPreCalc(spin * 3) + 1) * 0.5;
uint8_t r = 80 + 175 * v;
uint8_t g = 0;
uint8_t b = 120 + 135 * (1 - v);
return NeoPixel.Color(r, g, b);
}
float distToSegment(float px, float py, float x1, float y1, float x2, float y2) {
float vx = x2 - x1;
float vy = y2 - y1;
float wx = px - x1;
float wy = py - y1;
float c1 = vx * wx + vy * wy;
if (c1 <= 0) return sqrt((px - x1)*(px - x1) + (py - y1)*(py - y1));
float c2 = vx * vx + vy * vy;
if (c2 <= c1) return sqrt((px - x2)*(px - x2) + (py - y2)*(py - y2));
float b = c1 / c2;
float bx = x1 + b * vx;
float by = y1 + b * vy;
return sqrt((px - bx)*(px - bx) + (py - by)*(py - by));
}
uint32_t flyingWireCubeHard(uint8_t x, uint8_t y, float t) {
float cx = 9.5;
float cy = 9.5;
float time = t * 0.0015 / 2.0;
float cube[8][3] = {
{-1,-1,-1}, {1,-1,-1}, {1,1,-1}, {-1,1,-1},
{-1,-1, 1}, {1,-1, 1}, {1,1, 1}, {-1,1, 1}
};
const uint8_t edges[12][2] = {
{0,1},{1,2},{2,3},{3,0},
{4,5},{5,6},{6,7},{7,4},
{0,4},{1,5},{2,6},{3,7}
};
float zpos = fmod(time * 3.0, 6.0) + 2.0;
float scale = 7.0;
float rx = time * 1.3;
float ry = time * 0.9;
float rz = time * 0.7;
float px = x;
float py = y;
float proj[8][2];
for (int i = 0; i < 8; i++) {
float X = cube[i][0];
float Y = cube[i][1];
float Z = cube[i][2];
float y1 = Y * sinPreCalc(TWO_PI/4 - rx) - Z * sinPreCalc(rx);
float z1 = Y * sinPreCalc(rx) + Z * sinPreCalc(TWO_PI/4 - rx);
Y = y1; Z = z1;
float x2 = X * sinPreCalc(TWO_PI/4 - ry) + Z * sinPreCalc(ry);
float z2 = -X * sinPreCalc(ry) + Z * sinPreCalc(TWO_PI/4 - ry);
X = x2; Z = z2;
float x3 = X * sinPreCalc(TWO_PI/4 - rz) - Y * sinPreCalc(rz);
float y3 = X * sinPreCalc(rz) + Y * sinPreCalc(TWO_PI/4 - rz);
X = x3; Y = y3;
proj[i][0] = cx + X * scale;
proj[i][1] = cy + Y * scale;
}
bool onEdge = false;
const float thickness = 0.6; // edge thickness in pixels
for (int e = 0; e < 12; e++) {
int a = edges[e][0];
int b = edges[e][1];
float d = distToSegment(px, py,
proj[a][0], proj[a][1],
proj[b][0], proj[b][1]);
if (d < thickness) {
onEdge = true;
break;
}
}
if (onEdge) {
return NeoPixel.Color(0, 0, 255); // sharp neon wireframe
} else {
return NeoPixel.Color(0, 0, 0); // background off
}
}
bool isPacmanPixel(int px, int py, float cx, float cy, float r, float mouthOpen) {
float dx = px - cx;
float dy = py - cy;
float dist2 = dx*dx + dy*dy;
if (dist2 > r*r) return false;
float angle = atan2(dy, dx); // -PI..PI
// Mouth opening angle
float mouth = mouthOpen * 0.8; // max opening
if (angle > -mouth && angle < mouth) return false;
return true;
}
uint32_t pacman(uint8_t x, uint8_t y, uint32_t t) {
// Movement
float time = t * 0.005 / 3.0;
float cx = fmod(time * 6.0, 26.0) - 3.0; // move across screen
float cy = 10.0;
float r = 4.0;
// Mouth animation (chomp)
float mouth = (sinPreCalc(time * 6.0) + 1.0) * 0.5; // 0..1
// Optional pellets
int pelletX = ((int)(time * 6.0)) % 20;
bool pellet = (x == pelletX && y == 10);
if (isPacmanPixel(x, y, cx, cy, r, mouth)) {
return NeoPixel.Color(255, 220, 0); // Pac-Man yellow
}
if (pellet) {
return NeoPixel.Color(200, 200, 200); // pellet
}
return NeoPixel.Color(0, 0, 0);
}
uint32_t coolEffect(uint8_t x, uint8_t y, float t) {
// Center of the grid
float cx = 9.5;
float cy = 9.5;
float time = 0;
time = t / 100.0;
// Distance from center
float dx = x - cx;
float dy = y - cy;
float dist = sqrt(dx * dx + dy * dy);
// Animated wave
float wave = sinPreCalc(dist * 0.6 - time * 0.15);
// Rainbow hue shifts over time and space
float hue = dist * 20 + time * 3;
// Breathing brightness
float brightness = (sinPreCalc(time * 0.08) + 1.0) * 0.5; // 0..1
// Convert HSV → RGB (simple version)
uint8_t r, g, b;
float h = fmod(hue, 360.0);
int i = int(h / 60.0) % 6;
float f = (h / 60.0) - i;
float v = brightness * (0.5 + 0.5 * wave);
if (v < 0) v = 0;
if (v > 1) v = 1;
float p = 0;
float q = v * (1 - f);
float s = v * f;
float R, G, B;
switch (i) {
case 0: R = v; G = s; B = p; break;
case 1: R = q; G = v; B = p; break;
case 2: R = p; G = v; B = s; break;
case 3: R = p; G = q; B = v; break;
case 4: R = s; G = p; B = v; break;
default: R = v; G = p; B = q; break;
}
r = (uint8_t)(R * 255);
g = (uint8_t)(G * 255);
b = (uint8_t)(B * 255);
return NeoPixel.Color(r, g, b);
}
+32
View File
@@ -0,0 +1,32 @@
#ifndef ANIMATION_H
#define ANIMATION_H
#include <Arduino.h>
#include <Adafruit_NeoPixel.h>
extern Adafruit_NeoPixel NeoPixel;
extern const uint8_t imageManuBude[20][20];
uint32_t breathe(uint8_t x, uint8_t y, float t);
uint32_t galaxy(uint8_t x, uint8_t y, float t);
uint32_t flyingWireCubeHard(uint8_t x, uint8_t y, float t);
uint32_t pacman(uint8_t x, uint8_t y, uint32_t t);
uint32_t coolEffect(uint8_t x, uint8_t y, float t);
uint32_t creeper(uint8_t x, uint8_t y, uint32_t timestep);
uint32_t flappyBirdPixel(uint8_t x, uint8_t y, float time);
uint32_t xwingDeathStarPixel(uint8_t x, uint8_t y, float timeMs);
uint32_t nyanCatPixel(uint8_t x, uint8_t y, float timeMs);
uint32_t bonfireMoonPixel(uint8_t x, uint8_t y, float timeMs);
uint32_t jumpingJackPixel(uint8_t x, uint8_t y, float timeMs);
uint32_t spinningDavidStarPixel(uint8_t x, uint8_t y, float timeMs);
uint32_t starrySkyPixel(uint8_t x, uint8_t y, float timeMs);
uint32_t starrySky(uint8_t x, uint8_t y, float timeMs);
uint32_t purpleRain(uint8_t x, uint8_t y, float timeMs);
uint32_t amongUsPixel(uint8_t x, uint8_t y, float timeMs);
uint32_t minecraftPumpkin(uint8_t x, uint8_t y, float timeMs);
uint32_t bubbles(uint8_t x, uint8_t y, float timeMs);
int displayAnimationFrame(int timeMs, int CycleAnimationOn, int AnimationIndex);
uint8_t hash8(uint16_t x, uint16_t y);
#endif
+1126
View File
File diff suppressed because it is too large Load Diff
+256
View File
@@ -0,0 +1,256 @@
0.00000000f,
0.02454123f,
0.04906767f,
0.07356456f,
0.09801714f,
0.12241068f,
0.14673047f,
0.17096189f,
0.19509032f,
0.21910124f,
0.24298018f,
0.26671276f,
0.29028468f,
0.31368174f,
0.33688985f,
0.35989504f,
0.38268343f,
0.40524131f,
0.42755509f,
0.44961133f,
0.47139674f,
0.49289819f,
0.51410274f,
0.53499762f,
0.55557023f,
0.57580819f,
0.59569930f,
0.61523159f,
0.63439328f,
0.65317284f,
0.67155895f,
0.68954054f,
0.70710678f,
0.72424708f,
0.74095113f,
0.75720885f,
0.77301045f,
0.78834643f,
0.80320753f,
0.81758481f,
0.83146961f,
0.84485357f,
0.85772861f,
0.87008699f,
0.88192126f,
0.89322430f,
0.90398929f,
0.91420976f,
0.92387953f,
0.93299280f,
0.94154407f,
0.94952818f,
0.95694034f,
0.96377607f,
0.97003125f,
0.97570213f,
0.98078528f,
0.98527764f,
0.98917651f,
0.99247953f,
0.99518473f,
0.99729046f,
0.99879546f,
0.99969882f,
1.00000000f,
0.99969882f,
0.99879546f,
0.99729046f,
0.99518473f,
0.99247953f,
0.98917651f,
0.98527764f,
0.98078528f,
0.97570213f,
0.97003125f,
0.96377607f,
0.95694034f,
0.94952818f,
0.94154407f,
0.93299280f,
0.92387953f,
0.91420976f,
0.90398929f,
0.89322430f,
0.88192126f,
0.87008699f,
0.85772861f,
0.84485357f,
0.83146961f,
0.81758481f,
0.80320753f,
0.78834643f,
0.77301045f,
0.75720885f,
0.74095113f,
0.72424708f,
0.70710678f,
0.68954054f,
0.67155895f,
0.65317284f,
0.63439328f,
0.61523159f,
0.59569930f,
0.57580819f,
0.55557023f,
0.53499762f,
0.51410274f,
0.49289819f,
0.47139674f,
0.44961133f,
0.42755509f,
0.40524131f,
0.38268343f,
0.35989504f,
0.33688985f,
0.31368174f,
0.29028468f,
0.26671276f,
0.24298018f,
0.21910124f,
0.19509032f,
0.17096189f,
0.14673047f,
0.12241068f,
0.09801714f,
0.07356456f,
0.04906767f,
0.02454123f,
0.00000000f,
-0.02454123f,
-0.04906767f,
-0.07356456f,
-0.09801714f,
-0.12241068f,
-0.14673047f,
-0.17096189f,
-0.19509032f,
-0.21910124f,
-0.24298018f,
-0.26671276f,
-0.29028468f,
-0.31368174f,
-0.33688985f,
-0.35989504f,
-0.38268343f,
-0.40524131f,
-0.42755509f,
-0.44961133f,
-0.47139674f,
-0.49289819f,
-0.51410274f,
-0.53499762f,
-0.55557023f,
-0.57580819f,
-0.59569930f,
-0.61523159f,
-0.63439328f,
-0.65317284f,
-0.67155895f,
-0.68954054f,
-0.70710678f,
-0.72424708f,
-0.74095113f,
-0.75720885f,
-0.77301045f,
-0.78834643f,
-0.80320753f,
-0.81758481f,
-0.83146961f,
-0.84485357f,
-0.85772861f,
-0.87008699f,
-0.88192126f,
-0.89322430f,
-0.90398929f,
-0.91420976f,
-0.92387953f,
-0.93299280f,
-0.94154407f,
-0.94952818f,
-0.95694034f,
-0.96377607f,
-0.97003125f,
-0.97570213f,
-0.98078528f,
-0.98527764f,
-0.98917651f,
-0.99247953f,
-0.99518473f,
-0.99729046f,
-0.99879546f,
-0.99969882f,
-1.00000000f,
-0.99969882f,
-0.99879546f,
-0.99729046f,
-0.99518473f,
-0.99247953f,
-0.98917651f,
-0.98527764f,
-0.98078528f,
-0.97570213f,
-0.97003125f,
-0.96377607f,
-0.95694034f,
-0.94952818f,
-0.94154407f,
-0.93299280f,
-0.92387953f,
-0.91420976f,
-0.90398929f,
-0.89322430f,
-0.88192126f,
-0.87008699f,
-0.85772861f,
-0.84485357f,
-0.83146961f,
-0.81758481f,
-0.80320753f,
-0.78834643f,
-0.77301045f,
-0.75720885f,
-0.74095113f,
-0.72424708f,
-0.70710678f,
-0.68954054f,
-0.67155895f,
-0.65317284f,
-0.63439328f,
-0.61523159f,
-0.59569930f,
-0.57580819f,
-0.55557023f,
-0.53499762f,
-0.51410274f,
-0.49289819f,
-0.47139674f,
-0.44961133f,
-0.42755509f,
-0.40524131f,
-0.38268343f,
-0.35989504f,
-0.33688985f,
-0.31368174f,
-0.29028468f,
-0.26671276f,
-0.24298018f,
-0.21910124f,
-0.19509032f,
-0.17096189f,
-0.14673047f,
-0.12241068f,
-0.09801714f,
-0.07356456f,
-0.04906767f,
-0.02454123f