#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define JOYSTICK_X A0
#define JOYSTICK_Y A1
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire);
const uint8_t SNAKE_SIZE = 2;
uint8_t snake_x[128];
uint8_t snake_y[128];
uint8_t snake_length = 5;
uint8_t food_x, food_y;
int8_t dir_x = 1; // 1: right, -1: left
int8_t dir_y = 0; // 1: down, -1: up
bool game_over = false;
unsigned long last_update = 0;
const unsigned long UPDATE_RATE = 100;
void setup() {
pinMode(JOYSTICK_X, INPUT);
pinMode(JOYSTICK_Y, INPUT);
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.begin(9600);
Serial.println("SSD1306 allocation failed");
while (true);
}
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("Starting Snake Game");
display.display();
delay(2000); // Show startup message
resetGame();
}
void loop() {
if (game_over) {
display.clearDisplay();
display.setCursor(30, 28);
display.print("GAME OVER");
display.display();
delay(2000); // Pause before restarting
resetGame();
}
if (millis() - last_update > UPDATE_RATE) {
last_update = millis();
updateDirection();
moveSnake();
checkCollision();
display.clearDisplay();
displaySnake();
displayFood();
display.display();
}
}
void resetGame() {
snake_length = 5;
dir_x = 1;
dir_y = 0;
game_over = false;
for (uint8_t i = 0; i < snake_length; i++) {
snake_x[i] = 64 - i * SNAKE_SIZE;
snake_y[i] = 32;
}
spawnFood();
display.clearDisplay();
displaySnake();
displayFood();
display.display();
}
void updateDirection() {
int xValue = analogRead(JOYSTICK_X);
int yValue = analogRead(JOYSTICK_Y);
if (xValue < 400 && dir_x == 0) { // Joystick movimiento izquierdo
dir_x = 1;
dir_y = 0;
} else if (xValue > 600 && dir_x == 0) { // Joystick movimiento derecho
dir_x = -1;
dir_y = 0;
} else if (yValue < 400 && dir_y == 0) { // Joystick movimiento arriba
dir_x = 0;
dir_y = 1;
} else if (yValue > 600 && dir_y == 0) { // Joystick movimiento abajo
dir_x = 0;
dir_y = -1;
}
}
void moveSnake() {
for (int i = snake_length - 1; i > 0; i--) {
snake_x[i] = snake_x[i - 1];
snake_y[i] = snake_y[i - 1];
}
snake_x[0] += dir_x * SNAKE_SIZE;
snake_y[0] += dir_y * SNAKE_SIZE;
if (snake_x[0] == food_x && snake_y[0] == food_y) {
snake_length++;
spawnFood();
}
}
void checkCollision() {
if (snake_x[0] < 0 || snake_x[0] >= SCREEN_WIDTH || snake_y[0] < 0 || snake_y[0] >= SCREEN_HEIGHT) {
game_over = true;
}
for (uint8_t i = 1; i < snake_length; i++) {
if (snake_x[0] == snake_x[i] && snake_y[0] == snake_y[i]) {
game_over = true;
}
}
}
void displaySnake() {
for (uint8_t i = 0; i < snake_length; i++) {
display.fillRect(snake_x[i], snake_y[i], SNAKE_SIZE, SNAKE_SIZE, WHITE);
}
}
void spawnFood() {
food_x = random(0, SCREEN_WIDTH / SNAKE_SIZE) * SNAKE_SIZE;
food_y = random(0, SCREEN_HEIGHT / SNAKE_SIZE) * SNAKE_SIZE;
}
void displayFood() {
display.fillRect(food_x, food_y, SNAKE_SIZE, SNAKE_SIZE, WHITE);
}