#include <Adafruit_NeoPixel.h>
#define MATRIX_PIN 12
#define JOYSTICKBUTTON 11
//define analog values from joystick as integers
const int JOYSTICK_XPIN = A3;
const int JOYSTICK_YPIN = A4;
Adafruit_NeoPixel matrix = Adafruit_NeoPixel(256, MATRIX_PIN, NEO_GRB + NEO_KHZ800);
uint32_t RED = matrix.Color(255, 0, 0);
uint32_t GREEN = matrix.Color(0, 255, 0);
uint32_t BLUE = matrix.Color(0, 0, 255);
uint32_t BLUEDEATH = matrix.Color(0, 50, 250);
int snake[256];
int snakeNewPosition = 135, snakeLength, apple, col, row, snakeDirection, lastDirection;
int NewPosition, xpinval, ypinval;
unsigned long previousMillis;
unsigned long gameRate;
int numApplesEaten = 0;
struct Coordinate {
int row;
int col;
};
void setup() {
pinMode(JOYSTICK_XPIN, INPUT); //initializes pinMode of Joystick X direction
pinMode(JOYSTICK_YPIN, INPUT);
pinMode(JOYSTICKBUTTON, INPUT_PULLUP);
Serial.begin(115200);
matrix.begin();
matrix.setBrightness(15);
xpinval = joystickHome(JOYSTICK_XPIN);
ypinval = joystickHome(JOYSTICK_YPIN);
resetGameVariables();
generateSnake();
generateApple();
drawBoard();
}
void loop() {
unsigned long currentMillis = millis();
checkJoystickButton();
int Direction = SnakeDirection();
if (currentMillis - previousMillis >= gameRate) {
detectAppleEaten();
moveSnake(Direction);
drawBoard();
previousMillis = currentMillis;
lastDirection = Direction;
}
}
void generateSnake() {
for (int i = 0; i < snakeLength; i++) {
snake[i] = snakeNewPosition + i;
}
}
void drawBoard() {
matrix.setPixelColor(apple, RED);
for (int i = 0; i < snakeLength; i++) {
matrix.setPixelColor(snake[i], GREEN);
}
matrix.show();
}
int generateApple() {
apple = random(0, 256);
for (int i = 0; i < snakeLength; i++) {
if (snake[i] == apple) {
generateApple();
}
}
return apple;
}
void resetGameVariables() {
for (int i = 0; i < 256; i++) {
snake[i] = 0;
}
snakeLength = 2;
gameRate = 600;
generateApple();
snakeDirection = 1;
snakeNewPosition = 135;
}
void detectAppleEaten() {
if (snake[0] == apple) {
snakeLength += 1;
generateApple();
gameRate = .95 * gameRate;
}
}
void gameOver() {
for (int i = 0; i < snakeLength; i++) {
matrix.setPixelColor(snake[i], RED);
}
Serial.println("game over");
matrix.show();
delay(1000);
matrix.clear();
setup();
}
int SnakeDirection() {
int x = analogRead(JOYSTICK_XPIN);
int y = analogRead(JOYSTICK_YPIN);
if (x < (xpinval - 80) && lastDirection != 1) {
snakeDirection = 2;
} else if (x > (xpinval + 80) && lastDirection != 2) {
snakeDirection = 1;
} else if (y < (ypinval - 80) && lastDirection != 3) {
snakeDirection = 4;
} else if (y > (ypinval + 80) && lastDirection != 4) {
snakeDirection = 3;
}
return snakeDirection;
}
int joystickHome(int h) {
int tot = 0;
for (int i = 0; i < 6; i++) {
tot += analogRead(h);
}
int pinval = tot / 6;
return pinval;
}
int checkJoystickButton() {
if (digitalRead(JOYSTICKBUTTON) == 0) {
int values[] = {0, 100, 150, 255};
int R = values[random(0,3)];
int G = values[random(0,3)];
int B = values[random(0,3)];
GREEN = matrix.Color(R, G, B);
generateApple();
}
}
Coordinate findRowCol() {
Coordinate coord;
coord.row = snakeNewPosition / 16;
if (coord.row % 2 == 0) {
coord.col = snakeNewPosition % 16;
} else {
coord.col = 15 - (snakeNewPosition % 16);
}
return coord;
}
void moveSnake(int direction) {
snakeNewPosition = calculateNewPosition(direction);
for (int i = 0; i < snakeLength; i++) {
if (snake[i] == snakeNewPosition) {
gameOver();
}
}
matrix.clear();
for (int i = snakeLength; i > 0; i--) {
snake[i] = snake[i - 1];
}
snake[0] = snakeNewPosition;
}
int calculateNewPosition(int snakedirection) {
Coordinate coords = findRowCol();
int row = coords.row;
int col = coords.col;
int Direction = snakedirection;
if (Direction == 1 && row == 0) { //top edge
NewPosition = 255 - col;
} else if (Direction == 2 && row == 15) { //bottom edge
NewPosition = 255 - snakeNewPosition;
} else if (Direction == 3 && col == 0) { //left edge
if (row % 2 == 0) {
NewPosition = snakeNewPosition + 15;
} else {
NewPosition = snakeNewPosition - 15;
}
} else if (Direction == 4 && col == 15) { //right edge
if (row % 2 == 0) {
NewPosition = snakeNewPosition - 15;
} else {
NewPosition = snakeNewPosition + 15;
}
} else if (Direction == 1) { //up
if (row % 2 == 0) {
NewPosition = snakeNewPosition - (col * 2) - 1;
} else {
NewPosition = snakeNewPosition - (snakeNewPosition - 16 * row) - (16 - col);
}
} else if (Direction == 2) { //down
if (row % 2 == 0) {
NewPosition = snakeNewPosition + (16 - col - 1) + (16 - col);
} else {
NewPosition = snakeNewPosition + (col * 2) + 1;
}
} else if (Direction == 3) { //left
if (row % 2 == 0) {
NewPosition = snakeNewPosition - 1;
} else {
NewPosition = snakeNewPosition + 1;
}
} else if (Direction == 4) { //right
if (row % 2 == 0) {
NewPosition = snakeNewPosition + 1;
} else {
NewPosition = snakeNewPosition - 1;
}
}
return NewPosition;
}