#include #include #include #include #define clk PB13 #define din PB15 #define dc PB14 #define cs PB12 #define rst PA15 // Software SPI (slower updates, more flexible pin options): // pin 7 - Serial clock out (SCLK) // pin 6 - Serial data out (DIN) // pin 5 - Data/Command select (D/C) // pin 4 - LCD chip select (CS) // pin 3 - LCD reset (RST) Adafruit_PCD8544 display = Adafruit_PCD8544(clk, din, dc, cs, rst); //speed in ms #define SPEED 250 SimpleTimer timer; #define SNAKE_INIT_LENGTH 10 //Initial length of snake #define SNAKE_START_X 42 //Initial x position #define SNAKE_START_Y 20 //Initial y position //Pin setup according to the board #define left PA1 #define right PB8 #define up PA0 #define down PB9 #define center PC13 #define left_led PB6 #define right_led PB7 //Store the coordinates in a structure struct coordinates { int x; int y; }; std::vector snake; //store the snake points coordinates snake_last_piece; //store the last point | needed for visualisation coordinates food; //food coordinates bool leds = true; //for LED blink int direction = 0; int last_direction = 0; int points = 0; void setup() { // put your setup code here, to run once: //Serial port Serial.begin(9600); //Set inputs and outputs pinMode(left, INPUT_PULLUP); pinMode(right, INPUT_PULLUP); pinMode(up, INPUT_PULLUP); pinMode(down, INPUT_PULLUP); pinMode(center, INPUT_PULLUP); pinMode(left_led, OUTPUT); pinMode(right_led, OUTPUT); display.begin(); display.setContrast(63); display.display(); //show splashscreen delay(2000); display.clearDisplay(); init_game(); timer.setInterval(SPEED, TimerCallbackFunc); //Timer for moving the snake } void init_game() { /* * This function initializes the snake, clears the points and direction, and generate a new food. * Can be used to reset the game. */ //init the snake direction = 0; points = 0; snake.clear(); //clear the vector for(int i = 0; i < SNAKE_INIT_LENGTH; i++) { coordinates helper; helper.x = SNAKE_START_X - i; helper.y = SNAKE_START_Y; snake.push_back(helper); } snake_last_piece.x = 0; snake_last_piece.y = 0; generate_food(); } void TimerCallbackFunc() { //blinks the 2 LED digitalWrite(left_led, leds); digitalWrite(right_led, !leds); leds = !leds; //Moving in the given direction snake_move(direction); } void generate_food() { /* * Generates random x and y points until it's out of the snake's points. */ bool equal = true; while(equal) { equal = false; food.x = random(0, 83); food.y = random(0,47); for(int i = 0; i < snake.size(); i++) { if(snake[0].x == food.x && snake[0].y == food.y) { equal = true; } } } display.drawPixel(food.x, food.y, BLACK); display.display(); } void draw_snake() { /* * Draw the snake points. */ for(int i = 0; i < snake.size(); i++) { display.drawPixel(snake[i].x, snake[i].y, BLACK); } display.drawPixel(snake_last_piece.x, snake_last_piece.y, WHITE); display.display(); } bool check_crash() { /* * Returns true if the snake crashing into itself. */ for(int i = 1; i < snake.size(); i++) { if(snake[0].x == snake[i].x && snake[0].y == snake[i].y) { return true; } } return false; } void snake_move(int direction) { /* * Handling the moving directions and next points. */ last_direction = direction; snake_last_piece.x = snake[snake.size()-1].x; snake_last_piece.y = snake[snake.size()-1].y; coordinates helper; if(direction == 0) //right { helper = snake[0]; helper.x++; if(helper.x > 83) { helper.x = 0; } } else if(direction == 1) //left { helper = snake[0]; helper.x--; if(helper.x < 0) { helper.x = 83; } } else if(direction == 2) //up { helper = snake[0]; helper.y--; if(helper.y < 0) { helper.y = 47; } } else if(direction == 3) //down { helper = snake[0]; helper.y++; if(helper.y > 47) { helper.y = 0; } } //move forward every coordinate and replace the first with the new one for(int i = snake.size(); i > 0; i--) { snake[i] = snake [i-1]; } snake[0] = helper; draw_snake(); //if the snake ate the food, then increment by one and generate a new one if(snake[0].x == food.x && snake[0].y == food.y) { increment_snake(); generate_food(); } } void increment_snake() { snake.push_back(snake[snake.size()]); points++; } void loop() { // put your main code here, to run repeatedly: timer.run(); if(digitalRead(left) == 0) { Serial.print("Left button pressed"); if(last_direction != 0) { direction = 1; } } if(digitalRead(right) == 0) { Serial.print("Right button pressed"); if(last_direction != 1) { direction = 0; } } if(digitalRead(up) == 0) { Serial.print("Up button pressed"); if(last_direction != 3) { direction = 2; } } if(digitalRead(down) == 0) { Serial.print("Down button pressed"); if(last_direction != 2) { direction = 3; } } if(digitalRead(center) == 0) { Serial.print("Center button pressed"); display.drawPixel(food.x, food.y, BLACK); display.display(); } if(check_crash()) { display.clearDisplay(); display.setTextSize(1); display.setTextColor(BLACK); display.setCursor(0,0); display.println("Game over!"); //display.setCursor(0,10); display.println("Score: "); display.print(points, DEC); display.display(); while(digitalRead(center) != 0) { } display.clearDisplay(); init_game(); } }