#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);
}
void loop() {
float ball_x = sinf(millis() / 3000.f) * 5.f;
float ball_y = cosf(millis() / 3000.f) * 5.f;
float ball_radius = 3.f + sinf(millis() / 2000.f) * 2.5f;
float ball_transition = 3.5f + 2.5f * sinf(millis() / 300.f);
float max_sum_squares = ball_radius + ball_transition;
max_sum_squares *= max_sum_squares;
for (int screen_y = 0; screen_y < HEIGHT; screen_y++) {
for (int screen_x = 0; screen_x < WIDTH; screen_x++) {
float offset_x = ball_x + screen_x - WIDTH / 2;
float offset_y = ball_y + screen_y - HEIGHT / 2;
float sum_squares = offset_x * offset_x + offset_y * offset_y;
uint8_t coverage = 0;
if (sum_squares <= max_sum_squares) {
coverage = 255;
float distance = sqrtf(sum_squares) - ball_radius;
if (distance >= 0 && distance < ball_transition) {
float c = distance / ball_transition;
coverage = 255 - 255.f * c;
}
}
leds[XY(screen_x, screen_y)] = CRGB(coverage, coverage, coverage);
}
}
FastLED.show();
static uint8_t fps_frame = 0;
if (!++fps_frame)
Serial.println(FastLED.getFPS());
}