#include <FastLED.h>
#define WIDTH 16 //Ширина матрицы
#define HEIGHT 16 //Высота матрицы
#define LED_PIN 13 //Пин подключения матрицы на ардуино
#define BUTTON_PIN 2 //Пин подключения кнопки на ардуино
#define NUM_LEDS (WIDTH * HEIGHT) //Общее количество светодиодов
#define BRIGHTNESS 255 //Яркость (0-255)
#define COUNT_BALLOONS 3 //Количество шариков (1-5)
char MODE = 1; //1 - цвет от радиуса, 2 - цвет от пикселя
CRGB leds[NUM_LEDS]; //Массив для светодиодов
int balloons[COUNT_BALLOONS][3] = {-1}; //Инициализация шариков {x, y, angle}
char balloons_way[COUNT_BALLOONS][100][2] = {-1};//{x, y}
float HYPOTENUSE = sqrt(WIDTH * WIDTH + HEIGHT * HEIGHT) + 2;
char lenPush = 0; //Длина нажатия
void setup() {
FastLED.addLeds<WS2811, LED_PIN, GRB>(leds, NUM_LEDS);
FastLED.setBrightness(BRIGHTNESS);
pinMode(BUTTON_PIN, INPUT_PULLUP);
randomSeed(analogRead(0));
for (char i = 0; i < COUNT_BALLOONS; i++) {
for (char q = 0; q < 3; q++) {
balloons[i][q] = -1;
}
}
for (char i = 0; i < COUNT_BALLOONS; i++) {
for (char q = 0; q < 100; q++) {
for (char w = 0; w < 2; w++){
balloons_way[i][q][w] = -1;
}
}
}
for (char i = 0; i < COUNT_BALLOONS; i++) {//Создание шариков
balloons[i][0] = random(1, WIDTH - 1);
balloons[i][1] = random(1, HEIGHT - 1);
balloons[i][2] = random(-180, 181);
}
}
void NextStep() { //Функция обновления состояния доски
for (char i = 0; i < WIDTH; i++) { //Очистка светодиодов
for (char j = 0; j < HEIGHT; j++) {
leds[XY(i, j)] = CRGB::Black;
}
}
for (char i = 0; i < COUNT_BALLOONS; i++) {
bool line_drawn = false; //Начерчена ли линия?
for (char q = 0; q < 100; q++) {
if (balloons_way[i][q][0] != -1 && balloons_way[i][q][1] != -1) {
line_drawn = true;
break;
}
}
if (line_drawn == false) { //Если линия не начерчена, вычисляем её до границы
bool flag_qwe = false;
if (balloons[i][0] == 0 && balloons[i][1] == 0)
balloons[i][2] = random(10, 81);
else if (balloons[i][0] == 0 && balloons[i][1] == HEIGHT - 1)
balloons[i][2] = random(-80, -9);
else if (balloons[i][0] == WIDTH - 1 && balloons[i][1] == HEIGHT - 1)
balloons[i][2] = random(-170, -101);
else if (balloons[i][0] == WIDTH - 1 && balloons[i][1] == 0)
balloons[i][2] = random(100, 171);
else if (balloons[i][0] == 0 || balloons[i][0] == HEIGHT - 1)
balloons[i][2] = 180 - balloons[i][2];
else if (balloons[i][1] == 0 || balloons[i][1] == WIDTH - 1)
balloons[i][2] = -balloons[i][2];
char x1 = balloons[i][0];
char y1 = balloons[i][1];
char x2 = x1 + HYPOTENUSE * cos(balloons[i][2] * PI / 180);
char y2 = y1 + HYPOTENUSE * sin(balloons[i][2] * PI / 180);
const int deltaX = abs(x2 - x1);
const int deltaY = -abs(y2 - y1);
const int signX = x1 < x2 ? 1 : -1;
const int signY = y1 < y2 ? 1 : -1;
int error = deltaX + deltaY;
for (char q = 0; q < 100; q++) {
if (x1 <= -1 || y1 <= -1 || x1 >= WIDTH || y1 >= HEIGHT)//Если достигли границы, заканчивам вычисление
break;
balloons_way[i][q][0] = x1;
balloons_way[i][q][1] = y1;
int error2 = error * 2;
if(error2 >= deltaY) {
error += deltaY;
x1 += signX;
}
if(error2 <= deltaX) {
error += deltaX;
y1 += signY;
}
}
}
for (char q = 0; q < 100; q++) { //Передвигаем шарик на следующую позицию
if (balloons_way[i][q][0] != -1 && balloons_way[i][q][1] != -1) {
balloons[i][0] = balloons_way[i][q][0];
balloons[i][1] = balloons_way[i][q][1];
balloons_way[i][q][0] = -1;
balloons_way[i][q][1] = -1;
break;
}
}
if (i == 0)
leds[XY(balloons[i][0], balloons[i][1])] = CRGB(255, 0, 0);
else if (i == 1)
leds[XY(balloons[i][0], balloons[i][1])] = CRGB(0, 255, 0);
else if (i == 2)
leds[XY(balloons[i][0], balloons[i][1])] = CRGB(0, 0, 255);
else if (i == 3)
leds[XY(balloons[i][0], balloons[i][1])] = CRGB(139, 0, 255);
else if (i == 4)
leds[XY(balloons[i][0], balloons[i][1])] = CRGB(255, 255, 0);
}
}
int XY(char x, char y) { //Функция преобразования координат
//Для wokwi
return ((WIDTH - x) * WIDTH - (HEIGHT - y));
//Для реальной матрицы
/*if (x % 2 == 0)
return (x * WIDTH + y);
return (x * WIDTH + (WIDTH - y - 1));*/
}
void SetNextMode() { //Смена режима
for (char i = 0; i < WIDTH; i++) {
for (char j = 0; j < HEIGHT; j++) {
leds[XY(i, j)] = CRGB::Black;
}
}
if (MODE == 1)
MODE = 2;
else if (MODE == 2)
MODE = 1;
}
void loop() {
if (digitalRead(BUTTON_PIN) == LOW) {
lenPush += 1;
}
else if (digitalRead(BUTTON_PIN) != LOW && lenPush != 0) {
if (lenPush < 16)
SetNextMode();
lenPush = 0;
}
FastLED.show();
delay(50);
NextStep(); //Переход к следующему состоянию
}