#include "FastLED.h"

// Matrix size
#define LED_ROWS 32
#define LED_COLS 32
#define NUM_LEDS LED_ROWS * LED_COLS
// LEDs pin
#define DATA_PIN 3
// LED brightness
#define BRIGHTNESS 255
// Define the array of leds
CRGB leds[NUM_LEDS];

#define n ((NUM_LEDS > 128) ? NUM_LEDS / 128 : 1 )
#define restart (10) // sec
bool setUp = true; 
int8_t pos[2][n];
byte dir[n];
byte hue;
bool fade = false;

void move(byte id) {
  switch (dir[id]) {
    case 0: pos[1][id]++; break; //up
    case 1: pos[0][id]++; break; //right
    case 2: pos[1][id]--; break; //down
    case 3: pos[0][id]--; break; //left
  }
}
void check2(byte id) {
  if (leds[XY(pos[0][id], pos[1][id])] == CRGB(0, 0, 0))dir[id]++; else dir[id]--;
  if (dir[id] > 3) dir[id] = 0; else if (dir[id] < 0) dir[id] = 3;
}
void check3(byte id) {
 if(pos[0][id]> LED_COLS-1) pos[0][id]=0;
 if(pos[1][id]> LED_ROWS-1) pos[1][id]=0;
 if(pos[0][id]< 0) pos[0][id]=LED_COLS-1;
 if(pos[1][id]< 0) pos[1][id]=LED_ROWS-1;
}
void check1(byte id) {
  if (leds[XY(pos[0][id], pos[1][id])] == CRGB(0, 0, 0))leds[XY(pos[0][id], pos[1][id])] = CHSV(hue, 255, 255);else leds[XY(pos[0][id], pos[1][id])] = 0;}
void draw() {
  if(setUp){
    setUp = false;
    FastLED.clear();
    for(byte i=0; i<n; i++){
      pos[0][i] = random(0,LED_COLS);
      pos[1][i] = random(0,LED_ROWS);
      dir[i] = random(0, 3);
    }
  }
  for(byte i=0; i<n; i++){
  check1(i);
  move(i);
  check3(i);
  check2(i);}
  hue++;
  if(fade)fadeToBlackBy(leds, NUM_LEDS, 5);
  EVERY_N_SECONDS (restart){
   setUp = true; 
  }
}
void setup() {
  FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
  FastLED.setBrightness(BRIGHTNESS);
}

void loop() {
  draw();
  FastLED.show();
} //loop


uint16_t XY (uint8_t x, uint8_t y) {
  return (y * LED_COLS + x);
}