// ============= ЭФФЕКТЫ =============== // ------------- конфетти -------------- void sparklesRoutine() { for (uint8_t i = 0; i < modes[0].scale; i++) { uint8_t x = random(0, WIDTH); uint8_t y = random(0, HEIGHT); if (getPixColorXY(x, y) == 0) leds[getPixelNumber(x, y)] = CHSV(random(0, 255), 255, 255); } fader(70); } // функция плавного угасания цвета для всех пикселей void fader(uint8_t step) { for (uint8_t i = 0; i < WIDTH; i++) { for (uint8_t j = 0; j < HEIGHT; j++) { fadePixel(i, j, step); } } } void fadePixel(uint8_t i, uint8_t j, uint8_t step) // новый фейдер { int32_t pixelNum = getPixelNumber(i, j); if (getPixColor(pixelNum) == 0) return; if (leds[pixelNum].r >= 30 || leds[pixelNum].g >= 30 || leds[pixelNum].b >= 30) { leds[pixelNum].fadeToBlackBy(step); } else { leds[pixelNum] = 0; } } // ------------- огонь ----------------- #define SPARKLES 1 // вылетающие угольки вкл выкл unsigned char line[WIDTH]; int32_t pcnt = 0; //these values are substracetd from the generated values to give a shape to the animation const unsigned char valueMask[8][16] PROGMEM = { {32 , 0 , 0 , 0 , 0 , 0 , 0 , 32 , 32 , 0 , 0 , 0 , 0 , 0 , 0 , 32 }, {64 , 0 , 0 , 0 , 0 , 0 , 0 , 64 , 64 , 0 , 0 , 0 , 0 , 0 , 0 , 64 }, {96 , 32 , 0 , 0 , 0 , 0 , 32 , 96 , 96 , 32 , 0 , 0 , 0 , 0 , 32 , 96 }, {128, 64 , 32 , 0 , 0 , 32 , 64 , 128, 128, 64 , 32 , 0 , 0 , 32 , 64 , 128}, {160, 96 , 64 , 32 , 32 , 64 , 96 , 160, 160, 96 , 64 , 32 , 32 , 64 , 96 , 160}, {192, 128, 96 , 64 , 64 , 96 , 128, 192, 192, 128, 96 , 64 , 64 , 96 , 128, 192}, {255, 160, 128, 96 , 96 , 128, 160, 255, 255, 160, 128, 96 , 96 , 128, 160, 255}, {255, 192, 160, 128, 128, 160, 192, 255, 255, 192, 160, 128, 128, 160, 192, 255} }; //these are the hues for the fire, //should be between 0 (red) to about 25 (yellow) const unsigned char hueMask[8][16] PROGMEM = { {1 , 11, 19, 25, 25, 22, 11, 1 , 1 , 11, 19, 25, 25, 22, 11, 1 }, {1 , 8 , 13, 19, 25, 19, 8 , 1 , 1 , 8 , 13, 19, 25, 19, 8 , 1 }, {1 , 8 , 13, 16, 19, 16, 8 , 1 , 1 , 8 , 13, 16, 19, 16, 8 , 1 }, {1 , 5 , 11, 13, 13, 13, 5 , 1 , 1 , 5 , 11, 13, 13, 13, 5 , 1 }, {1 , 5 , 11, 11, 11, 11, 5 , 1 , 1 , 5 , 11, 11, 11, 11, 5 , 1 }, {0 , 1 , 5 , 8 , 8 , 5 , 1 , 0 , 0 , 1 , 5 , 8 , 8 , 5 , 1 , 0 }, {0 , 0 , 1 , 5 , 5 , 1 , 0 , 0 , 0 , 0 , 1 , 5 , 5 , 1 , 0 , 0 }, {0 , 0 , 0 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 0 , 0 , 0 } }; void fireRoutine() { if (loadingFlag) { loadingFlag = false; //FastLED.clear(); generateLine(); } if (pcnt >= 100) { shiftUp(); generateLine(); pcnt = 0; } drawFrame(pcnt); pcnt += 30; } // Randomly generate the next line (matrix row) void generateLine() { for (uint8_t x = 0; x < WIDTH; x++) { line[x] = random(64, 255); } } void shiftUp() { for (uint8_t y = HEIGHT - 1; y > 0; y--) { for (uint8_t x = 0; x < WIDTH; x++) { uint8_t newX = x; if (x > 15) newX = x - 15; if (y > 7) continue; matrixValue[y][newX] = matrixValue[y - 1][newX]; } } for (uint8_t x = 0; x < WIDTH; x++) { uint8_t newX = x; if (x > 15) newX = x - 15; matrixValue[0][newX] = line[newX]; } } // draw a frame, interpolating between 2 "key frames" // @param pcnt percentage of interpolation void drawFrame(int32_t pcnt) { int32_t nextv; //each row interpolates with the one before it for (unsigned char y = HEIGHT - 1; y > 0; y--) { for (unsigned char x = 0; x < WIDTH; x++) { uint8_t newX = x; if (x > 15) newX = x - 15; if (y < 8) { nextv = (((100.0 - pcnt) * matrixValue[y][newX] + pcnt * matrixValue[y - 1][newX]) / 100.0) - pgm_read_byte(&(valueMask[y][newX])); CRGB color = CHSV( modes[1].scale * 2.5 + pgm_read_byte(&(hueMask[y][newX])), // H 255, // S (uint8_t)max(0, nextv) // V ); leds[getPixelNumber(x, y)] = color; } else if (y == 8 && SPARKLES) { if (random(0, 20) == 0 && getPixColorXY(x, y - 1) != 0) drawPixelXY(x, y, getPixColorXY(x, y - 1)); else drawPixelXY(x, y, 0); } else if (SPARKLES) { // старая версия для яркости if (getPixColorXY(x, y - 1) > 0) drawPixelXY(x, y, getPixColorXY(x, y - 1)); else drawPixelXY(x, y, 0); } } } //first row interpolates with the "next" line for (unsigned char x = 0; x < WIDTH; x++) { uint8_t newX = x; if (x > 15) newX = x - 15; CRGB color = CHSV( modes[1].scale * 2.5 + pgm_read_byte(&(hueMask[0][newX])), // H 255, // S (uint8_t)(((100.0 - pcnt) * matrixValue[0][newX] + pcnt * line[newX]) / 100.0) // V ); leds[getPixelNumber(newX, 0)] = color; } } uint8_t hue; // ------------- радуга ---------------- void rainbowVertical() { hue += 2; for (uint8_t j = 0; j < HEIGHT; j++) { CHSV thisColor = CHSV((uint8_t)(hue + j * modes[2].scale), 255, 255); for (uint8_t i = 0; i < WIDTH; i++) drawPixelXY(i, j, thisColor); } } void rainbowHorizontal() { hue += 2; for (uint8_t i = 0; i < WIDTH; i++) { CHSV thisColor = CHSV((uint8_t)(hue + i * modes[3].scale), 255, 255); for (uint8_t j = 0; j < HEIGHT; j++) drawPixelXY(i, j, thisColor); //leds[getPixelNumber(i, j)] = thisColor; } } // ------------- цвета ----------------- void colorsRoutine() { hue += modes[4].scale; for (int32_t i = 0; i < NUM_LEDS; i++) { leds[i] = CHSV(hue, 255, 255); } } // ------------- цвет ------------------ void colorRoutine() { for (int32_t i = 0; i < NUM_LEDS; i++) { leds[i] = CHSV(modes[14].scale * 2.5, 255, 255); } } // ------------- снегопад 2.0 ---------- void snowRoutine() { // сдвигаем всё вниз for (uint8_t x = 0; x < WIDTH; x++) { for (uint8_t y = 0; y < HEIGHT - 1; y++) { drawPixelXY(x, y, getPixColorXY(x, y + 1)); } } for (uint8_t x = 0; x < WIDTH; x++) { // заполняем случайно верхнюю строку // а также не даём двум блокам по вертикали вместе быть if (getPixColorXY(x, HEIGHT - 2) == 0 && (random(0, 100 - modes[15].scale) == 0)) drawPixelXY(x, HEIGHT - 1, 0xE0FFFF - 0x101010 * random(0, 4)); else drawPixelXY(x, HEIGHT - 1, 0x000000); } } // ------------- матрица --------------- void matrixRoutine() { for (uint8_t x = 0; x < WIDTH; x++) { // заполняем случайно верхнюю строку uint32_t thisColor = getPixColorXY(x, HEIGHT - 1); if (thisColor == 0) drawPixelXY(x, HEIGHT - 1, 0x00FF00 * (random(0, 100 - modes[16].scale) == 0)); else if (thisColor < 0x002000) drawPixelXY(x, HEIGHT - 1, 0); else drawPixelXY(x, HEIGHT - 1, thisColor - 0x002000); } // сдвигаем всё вниз for (uint8_t x = 0; x < WIDTH; x++) { for (uint8_t y = 0; y < HEIGHT - 1; y++) { drawPixelXY(x, y, getPixColorXY(x, y + 1)); } } } // ------------- светляки -------------- #define LIGHTERS_AM 100 int32_t lightersPos[2][LIGHTERS_AM]; int8_t lightersSpeed[2][LIGHTERS_AM]; CHSV lightersColor[LIGHTERS_AM]; uint8_t loopCounter; int32_t angle[LIGHTERS_AM]; int32_t speedV[LIGHTERS_AM]; int8_t angleSpeed[LIGHTERS_AM]; void lightersRoutine() { if (loadingFlag) { loadingFlag = false; randomSeed(millis()); for (uint8_t i = 0; i < LIGHTERS_AM; i++) { lightersPos[0][i] = random(0, WIDTH * 10); lightersPos[1][i] = random(0, HEIGHT * 10); lightersSpeed[0][i] = random(-10, 10); lightersSpeed[1][i] = random(-10, 10); lightersColor[i] = CHSV(random(0, 255), 255, 255); } } FastLED.clear(); if (++loopCounter > 20) loopCounter = 0; for (uint8_t i = 0; i < modes[17].scale; i++) { if (loopCounter == 0) // меняем скорость каждые 255 отрисовок { lightersSpeed[0][i] += random(-3, 4); lightersSpeed[1][i] += random(-3, 4); lightersSpeed[0][i] = constrain(lightersSpeed[0][i], -20, 20); lightersSpeed[1][i] = constrain(lightersSpeed[1][i], -20, 20); } lightersPos[0][i] += lightersSpeed[0][i]; lightersPos[1][i] += lightersSpeed[1][i]; if (lightersPos[0][i] < 0) lightersPos[0][i] = (WIDTH - 1) * 10; if (lightersPos[0][i] >= WIDTH * 10) lightersPos[0][i] = 0; if (lightersPos[1][i] < 0) { lightersPos[1][i] = 0; lightersSpeed[1][i] = -lightersSpeed[1][i]; } if (lightersPos[1][i] >= (HEIGHT - 1) * 10) { lightersPos[1][i] = (HEIGHT - 1) * 10; lightersSpeed[1][i] = -lightersSpeed[1][i]; } drawPixelXY(lightersPos[0][i] / 10, lightersPos[1][i] / 10, lightersColor[i]); } } /* void lightersRoutine() { if (loadingFlag) { loadingFlag = false; randomSeed(millis()); for (uint8_t i = 0; i < LIGHTERS_AM; i++) { lightersPos[0][i] = random(0, WIDTH * 10); lightersPos[1][i] = random(0, HEIGHT * 10); lightersColor[i] = CHSV(random(0, 255), 255, 255); speedV[i] = random(5, 10); angle[i] = random(0, 360); angleSpeed[i] = random(-10, 10); } } FastLED.clear(); if (++loopCounter > 20) loopCounter = 0; for (uint8_t i = 0; i < modes[17].scale; i++) { if (loopCounter == 0) // меняем скорость каждые 255 отрисовок { angleSpeed[i] += random(-3, 4); angleSpeed[i] = constrain(angleSpeed[i], -15, 15); } lightersPos[0][i] += speedV[i] * cos(radians(angle[i])); lightersPos[1][i] += speedV[i] * sin(radians(angle[i])); if (lightersPos[0][i] < 0) lightersPos[0][i] = (WIDTH - 1) * 10; if (lightersPos[0][i] >= WIDTH * 10) lightersPos[0][i] = 0; if (lightersPos[1][i] < 0) { lightersPos[1][i] = 0; angle[i] = 360 - angle[i]; } else { angle[i] += angleSpeed[i]; } if (lightersPos[1][i] >= (HEIGHT - 1) * 10) { lightersPos[1][i] = (HEIGHT - 1) * 10; angle[i] = 360 - angle[i]; } else { angle[i] += angleSpeed[i]; } if (angle[i] > 360) angle[i] = 360 - angle[i]; if (angle[i] < 0) angle[i] = 360 + angle[i]; drawPixelXY(lightersPos[0][i] / 10, lightersPos[1][i] / 10, lightersColor[i]); } } */