#include <FastLED.h>
#define WIDTH 16
#define HEIGHT 16
#define NUM_LEDS ((WIDTH) * (HEIGHT))
CRGB leds[NUM_LEDS + 1];
uint16_t XY(uint8_t x, uint8_t y) {
if (x >= WIDTH) return NUM_LEDS;
if (y >= HEIGHT) return NUM_LEDS;
if (y & 1)
return (y + 1) * WIDTH - 1 - x;
else
return y * WIDTH + x;
}
void setup() {
Serial.begin(115200);
FastLED.addLeds<NEOPIXEL, 3>(leds, NUM_LEDS);
FastLED.setCorrection(UncorrectedColor);
FastLED.setTemperature(UncorrectedTemperature);
FastLED.setDither(DISABLE_DITHER);
}
struct Ball {
float x_speed, y_speed, radius, transition;
CRGB colour;
};
Ball balls[] = {
{8, 9.58, 1.5, 10, CRGB::Red},
{7, 7.2, 1.5, 10, CRGB::Green},
{6, 6.5, 1.5, 10, CRGB::Blue},
};
void loop() {
for (auto b = 0; b < sizeof(balls) / sizeof(*balls); b++) {
float offset_x = sinf(balls[b].x_speed * millis() / 8192.f) * WIDTH / 2 - WIDTH / 2;
float offset_y = cosf(balls[b].y_speed * millis() / 8192.f) * HEIGHT / 2 - HEIGHT / 2;
float radius = balls[b].radius;
float transition = balls[b].transition;
float max_sum_squares = powf(radius + transition, 2);
for (int y = 0; y < HEIGHT; y++) {
for (int x = 0; x < WIDTH; x++) {
float sum_squares = powf(x + offset_x, 2) + powf(y + offset_y, 2);
if (sum_squares > max_sum_squares)
continue;
CRGB faded = balls[b].colour;
float distance = sqrtf(sum_squares) - radius;
if (distance >= 0)
faded %= 255 - 255.f * distance / transition;
leds[XY(x, y)] += faded;
}
}
}
FastLED.show();
FastLED.clear();
static uint8_t fps_frame = 0;
if (!++fps_frame)
Serial.println(FastLED.getFPS());
}