#include <Adafruit_NeoPixel.h>
#include <math.h> // 为等离子和波纹扩展引入数学库
#define MATRIX_PIN 16
#define ROWS 8
#define COLS 8
#define NUM_PIXELS (ROWS * COLS)
Adafruit_NeoPixel matrix(NUM_PIXELS, MATRIX_PIN, NEO_GRB + NEO_KHZ800);
uint32_t Wheel(byte WheelPos) {
WheelPos = 255 - WheelPos;
if (WheelPos < 85) {
return matrix.Color(255 - WheelPos * 3, 0, WheelPos * 3);
} else if (WheelPos < 170) {
WheelPos -= 85;
return matrix.Color(0, WheelPos * 3, 255 - WheelPos * 3);
} else {
WheelPos -= 170;
return matrix.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}
}
void setup() {
matrix.begin();
matrix.setBrightness(50);
matrix.show();
}
// ================= 原有代码(仅在末尾追加了 1 行调用) =================
void loop() {
static uint16_t offset = 0;
for (int row = 0; row < ROWS; row++) {
for (int col = 0; col < COLS; col++) {
int pixel = row * COLS + col;
// Spread rainbow across rows and columns
byte colorIndex = ((row + col) * 256 / (ROWS + COLS) + offset) & 255;
matrix.setPixelColor(pixel, Wheel(colorIndex));
}
}
matrix.show();
offset = (offset + 1) & 255;
delay(30);
// 【新增】:调用扩展特效总调度器。原有动画运行 20 秒后,自动进入特效大赏。
runAdvancedEffects();
}
// =========================================================================
// ================= 以下为新增的扩展功能模块(不修改上方任何代码) =================
// 特效调度器:每 20 秒循环触发一次特效大赏,总特效时长约 50 秒
void runAdvancedEffects() {
static uint32_t lastExtTime = 0;
static bool initialized = false;
// 初始化一次随机种子
if (!initialized) {
randomSeed(analogRead(0));
initialized = true;
}
// 前 20 秒:运行原版对角线彩虹动画
if (millis() - lastExtTime < 20000) return;
// 开始特效大赏(依次执行,每个特效自动设置持续时间)
centerRipple(15); // 1. 中心扩散
auroraWaves(15); // 2. 极光波浪
plasmaEffect(20); // 3. 等离子体
fireEffect(30); // 4. 烈焰燃烧
matrixRain(25); // 5. 数字雨
snakeEffect(30); // 6. 贪吃蛇
bouncingBall(25); // 7. 弹跳球
snowEffect(20); // 8. 下雪
rainbowChase(20); // 9. 彩虹追逐
twinkle(40); // 10. 星光闪烁
// 结束后清屏,准备切回原有动画
matrix.clear();
matrix.show();
lastExtTime = millis();
}
// 1. 中心扩散彩虹
void centerRipple(int wait) {
uint32_t startTime = millis();
uint16_t offset = 0;
while (millis() - startTime < 5000) {
for (int row = 0; row < ROWS; row++) {
for (int col = 0; col < COLS; col++) {
float dist = sqrt(pow(row - 3.5, 2) + pow(col - 3.5, 2));
byte colorIndex = ((int)(dist * 25) + offset) & 255;
matrix.setPixelColor(row * COLS + col, Wheel(colorIndex));
}
}
matrix.show();
offset = (offset + 2) & 255;
delay(wait);
}
}
// 2. 极光波浪
void auroraWaves(int wait) {
uint32_t startTime = millis();
float time = 0.0;
while (millis() - startTime < 5000) {
for (int row = 0; row < ROWS; row++) {
for (int col = 0; col < COLS; col++) {
float wave1 = sin(row * 0.6 + time);
float wave2 = cos(col * 0.4 + time * 0.8);
float val = (wave1 + wave2 + 2.0) / 4.0;
byte hue = (byte)(85 + val * 85 + time * 10);
uint32_t color = Wheel(hue);
uint8_t r = (uint8_t)((color >> 16) * (0.2 + 0.8 * val));
uint8_t g = (uint8_t)((color >> 8) * (0.2 + 0.8 * val));
uint8_t b = (uint8_t)(color * (0.2 + 0.8 * val));
matrix.setPixelColor(row * COLS + col, matrix.Color(r, g, b));
}
}
matrix.show();
time += 0.1;
delay(wait);
}
}
// 3. 等离子体(Plasma)
void plasmaEffect(int wait) {
uint32_t startTime = millis();
float time = 0.0;
while (millis() - startTime < 5000) {
for (int row = 0; row < ROWS; row++) {
for (int col = 0; col < COLS; col++) {
// 多重正弦波叠加产生等离子效果
float v = sin(col * 0.5 + time) + sin(row * 0.5 + time) +
sin((col + row) * 0.5 + time) + sin(sqrt(col*col + row*row) * 0.5 + time);
byte hue = (byte)((v + 4) * 32 + time * 20);
matrix.setPixelColor(row * COLS + col, Wheel(hue));
}
}
matrix.show();
time += 0.15;
delay(wait);
}
}
// 4. 烈焰燃烧
void fireEffect(int wait) {
uint32_t startTime = millis();
byte heat[ROWS][COLS];
memset(heat, 0, sizeof(heat));
while (millis() - startTime < 5000) {
// 1. 冷却
for (int row = 0; row < ROWS; row++) {
for (int col = 0; col < COLS; col++) {
heat[row][col] = (heat[row][col] > 10) ? heat[row][col] - 10 : 0;
}
}
// 2. 热量向上传播
for (int row = 0; row < ROWS - 1; row++) {
for (int col = 0; col < COLS; col++) {
heat[row][col] = (heat[row][col] + heat[row+1][col] + heat[row+1][(col+1)%COLS]) / 3;
}
}
// 3. 底部随机点火
for (int col = 0; col < COLS; col++) {
if (random(10) < 6) heat[ROWS-1][col] = random(180, 255);
}
// 4. 渲染火焰
for (int row = 0; row < ROWS; row++) {
for (int col = 0; col < COLS; col++) {
byte h = heat[row][col];
// 火焰调色板:黑 -> 红 -> 黄 -> 白
if (h < 85) matrix.setPixelColor(row*COLS+col, matrix.Color(h*3, 0, 0));
else if (h < 170) matrix.setPixelColor(row*COLS+col, matrix.Color(255, (h-85)*3, 0));
else matrix.setPixelColor(row*COLS+col, matrix.Color(255, 255, (h-170)*3));
}
}
matrix.show();
delay(wait);
}
}
// 5. 数字雨(矩阵雨)
void matrixRain(int wait) {
int dropPos[COLS];
for (int i = 0; i < COLS; i++) dropPos[i] = random(-10, 0);
uint32_t startTime = millis();
while (millis() - startTime < 5000) {
// 渐暗拖尾
for (int i = 0; i < NUM_PIXELS; i++) {
uint32_t color = matrix.getPixelColor(i);
matrix.setPixelColor(i, matrix.Color(
((color >> 16) & 0xFF) * 0.75,
((color >> 8) & 0xFF) * 0.75,
(color & 0xFF) * 0.75));
}
// 绘制雨滴
for (int col = 0; col < COLS; col++) {
if (dropPos[col] >= 0 && dropPos[col] < ROWS) {
matrix.setPixelColor(dropPos[col] * COLS + col, matrix.Color(0, 255, 0));
if (dropPos[col] > 0) matrix.setPixelColor((dropPos[col]-1) * COLS + col, matrix.Color(0, 150, 0));
}
if (random(10) < 3) {
dropPos[col]++;
if (dropPos[col] >= ROWS + 5) dropPos[col] = random(-5, 0);
}
}
matrix.show();
delay(wait);
}
}
// 6. 贪吃蛇
void snakeEffect(int wait) {
uint32_t startTime = millis();
int snakeX[64], snakeY[64], snakeLen = 3;
int dir = 0; // 0上 1右 2下 3左
int headX = 3, headY = 3;
int foodX = random(0, COLS), foodY = random(0, ROWS);
memset(snakeX, 0, sizeof(snakeX)); memset(snakeY, 0, sizeof(snakeY));
while (millis() - startTime < 8000) {
// 更新蛇身
for (int i = snakeLen - 1; i > 0; i--) {
snakeX[i] = snakeX[i-1]; snakeY[i] = snakeY[i-1];
}
snakeX[0] = headX; snakeY[0] = headY;
// 移动方向逻辑(简单AI,避免撞墙和撞自己)
if (random(10) < 2) dir = random(0, 4);
if (dir == 0) headY--; else if (dir == 1) headX++;
else if (dir == 2) headY++; else headX--;
// 边界处理
if (headX < 0) headX = COLS - 1; else if (headX >= COLS) headX = 0;
if (headY < 0) headY = ROWS - 1; else if (headY >= ROWS) headY = 0;
// 吃食物
if (headX == foodX && headY == foodY) {
snakeLen = (snakeLen < 20) ? snakeLen + 1 : 20;
foodX = random(0, COLS); foodY = random(0, ROWS);
}
// 渲染
matrix.clear();
matrix.setPixelColor(foodX * COLS + foodY, matrix.Color(255, 0, 0));
for (int i = 0; i < snakeLen; i++) {
matrix.setPixelColor(snakeY[i] * COLS + snakeX[i], matrix.Color(0, 255, 0));
}
matrix.show();
delay(wait * 3);
}
}
// 7. 弹跳球
void bouncingBall(int wait) {
uint32_t startTime = millis();
float x = 3.5, y = 3.5, vx = 0.35, vy = 0.25;
matrix.clear();
while (millis() - startTime < 5000) {
// 运动
x += vx; y += vy;
if (x <= 0 || x >= COLS - 1) vx = -vx;
if (y <= 0 || y >= ROWS - 1) vy = -vy;
// 限制边界
if (x < 0) x = 0; if (x > COLS - 1) x = COLS - 1;
if (y < 0) y = 0; if (y > ROWS - 1) y = ROWS - 1;
// 渲染(带拖尾)
for (int i = 0; i < NUM_PIXELS; i++) {
uint32_t c = matrix.getPixelColor(i);
matrix.setPixelColor(i, matrix.Color(((c>>16)&0xFF)*0.6, ((c>>8)&0xFF)*0.6, (c&0xFF)*0.6));
}
matrix.setPixelColor((int)y * COLS + (int)x, matrix.Color(255, 255, 255));
matrix.show();
delay(wait);
}
}
// 8. 下雪效果
void snowEffect(int wait) {
uint32_t startTime = millis();
float snowY[COLS];
for(int i=0; i<COLS; i++) snowY[i] = random(-10, 0);
while (millis() - startTime < 5000) {
matrix.clear();
for (int col = 0; col < COLS; col++) {
int y = (int)snowY[col];
if (y >= 0 && y < ROWS) {
matrix.setPixelColor(y * COLS + col, matrix.Color(100, 100, 255)); // 雪花
}
snowY[col] += 0.2 + (random(0, 100) / 500.0);
if (snowY[col] >= ROWS) snowY[col] = random(-5, 0);
}
matrix.show();
delay(wait);
}
}
// 9. 彩虹追逐
void rainbowChase(int wait) {
uint32_t startTime = millis();
uint16_t offset = 0;
while (millis() - startTime < 5000) {
for (int i = 0; i < NUM_PIXELS; i++) {
// 根据像素位置和时间计算色相
byte hue = (i * 256 / NUM_PIXELS + offset) & 255;
matrix.setPixelColor(i, Wheel(hue));
}
matrix.show();
offset = (offset + 3) & 255;
delay(wait);
}
}
// 10. 随机星光闪烁
void twinkle(int wait) {
uint32_t startTime = millis();
matrix.clear();
while (millis() - startTime < 4000) {
for (int i = 0; i < 4; i++) {
matrix.setPixelColor(random(0, NUM_PIXELS), matrix.Color(255, 255, 255));
}
matrix.show();
delay(wait);
// 缓慢衰减
for (int i = 0; i < NUM_PIXELS; i++) {
uint32_t c = matrix.getPixelColor(i);
uint8_t r = (c >> 16) & 0xFF, g = (c >> 8) & 0xFF, b = c & 0xFF;
r = (r > 15) ? r - 15 : 0;
g = (g > 15) ? g - 15 : 0;
b = (b > 15) ? b - 15 : 0;
matrix.setPixelColor(i, matrix.Color(r, g, b));
}
}
}