#include <FastLED.h>
// LED matrix and joystick setup
#define LED_TYPE WS2812B
#define NUM_LEDS 64
#define DATA_PIN 3
#define VERT_PIN A0
#define HORZ_PIN A1
#define SEL_PIN 2
CRGB leds[NUM_LEDS];
// Helper to map LED coordinates
void controlLED(int y, int x, CRGB color) {
if (x < 0 || x > 7 || y < 0 || y > 7) return;
int ledIndex = y * 8 + x;
leds[ledIndex] = color;
}
// Classes for the game
class Head {
public:
int x = 3;
int y = 3;
void move(int dx, int dy) {
x += dx;
y += dy;
}
void draw() {
controlLED(y, x, CRGB::Green); // green
}
};
class Body {
private:
struct Segment {
int x, y;
};
Segment segments[64];
int length = 1;
public:
void addSegment(int x, int y) {
for (int i = length; i > 0; i--) {
segments[i] = segments[i - 1];
}
segments[0] = {x, y};
length++;
}
void move(int newX, int newY) {
for (int i = length - 1; i > 0; i--) {
segments[i] = segments[i - 1];
}
segments[0] = {newX, newY};
}
void draw() {
for (int i = 0; i < length; i++) {
controlLED(segments[i].y, segments[i].x, CRGB::Green); // green
}
}
bool checkCollision(int x, int y) {
for (int i = 0; i < length; i++) {
if (segments[i].x == x && segments[i].y == y) {
return true; // Collision detected
}
}
return false; // No collision
}
int getLength() { return length; }
};
class Apple {
public:
int x = random(0, 8);
int y = random(0, 8);
bool teleport = false; // faketeleport
void spawn() {
x = random(0, 8);
y = random(0, 8);
teleport = random(0, 100) < 50; // oopsie...
}
void draw() {
controlLED(y, x, teleport ? CRGB::Blue : CRGB::Red);
}
};
class Game {
private:
Head head;
Body body;
Apple apple;
int dx = 1, dy = 0;
void readJoystick() {
int vert = analogRead(HORZ_PIN);
int horz = analogRead(VERT_PIN);
// Исправление направления джойстика
if (vert < 400 && dy == 0) { dx = 0; dy = 1; } // Вниз
if (vert > 600 && dy == 0) { dx = 0; dy = -1; } // Вверх
if (horz < 400 && dx == 0) { dx = -1; dy = 0; } // Влево
if (horz > 600 && dx == 0) { dx = 1; dy = 0; } // Вправо
}
void gameOver() {
FastLED.clear();
for (int i = 0; i < 3; i++) {
FastLED.showColor(CRGB::White);
delay(300);
FastLED.clear();
delay(300);
}
reset();
}
/*void win() {
FastLED.clear();
for (int i = 0; i < 3; i++) {
FastLED.showColor(CRGB::Green);
delay(300);
FastLED.clear();
delay(300);
}
reset();
}*/
public:
void update() {
int newX = head.x + dx;
int newY = head.y + dy;
// Check boundaries
if (newX < 0 || newX > 7 || newY < 0 || newY > 7) {
gameOver();
return;
}
// Check collision with body
if (body.checkCollision(newX, newY)) {
gameOver();
return;
}
// Check if apple is eaten
if (newX == apple.x && newY == apple.y) {
if (!apple.teleport) { // orig? good
body.addSegment(head.x, head.y);
}
if (apple.teleport) {
head.x = random(2,5);
head.y = random(2,5);
}
apple.spawn(); // Спавним новое яблоко
}
else {
body.move(head.x, head.y);
}
head.move(dx, dy);
}
void draw() {
FastLED.clear();
apple.draw(); // Отрисовка яблока
body.draw(); // Отрисовка тела (синее)
head.draw(); // Отрисовка головы (зелёная)
FastLED.show();
}
void reset() {
head = Head();
body = Body();
apple = Apple();
dx = 1;
dy = 0;
apple.spawn();
}
void run() {
readJoystick();
update();
draw();
}
};
Game snakeGame;
void setup() {
FastLED.addLeds<LED_TYPE, DATA_PIN, GRB>(leds, NUM_LEDS);
pinMode(VERT_PIN, INPUT);
pinMode(HORZ_PIN, INPUT);
pinMode(SEL_PIN, INPUT_PULLUP);
Serial.begin(9600);
}
void loop() {
snakeGame.run();
delay(300);
}