beefviper

Snake for Arduino Uno with 128x64 LCD

Jan 8th, 2017
437
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2.  Name:      Snake.ino
  3.  Created:   12/29/2016 5:15:15 AM
  4.  Author:    beefviper
  5. */
  6.  
  7. // Include U8g2 library for JHD529M1-12864F (ST7920) 128X64 monochrome LCD display
  8. #include <U8g2lib.h>
  9.  
  10. // u8g2 LCD configuration line: _1 (single page) _6800 (comm mode) _R2 (180rotate), 8 data lines, 3 control lines
  11. U8G2_ST7920_128X64_1_6800 u8g2(U8G2_R2, 8, 9, 10, 11, 4, 5, 6, 7, /*enable=*/ 18 /* A4 */, /*cs=*/ U8X8_PIN_NONE, /*dc/rs=*/ 17 /* A3 */, /*reset=*/ 15 /* A1 */);  // Remember to set R/W to 0
  12.  
  13. // Pin Assignments
  14. const int xAxisPin    = 16;
  15. const int yAxisPin    = 19;
  16. const int buttonPin   =  2;
  17. const int speakerPin  =  3;
  18. const int floatingPin = 14;
  19.  
  20. // Hardware Constants
  21. const int screenWidth  = 128;
  22. const int screenHeight =  64;
  23.  
  24. // Joystick Variables
  25. int joyX = 0;
  26. int joyY = 0;
  27. int joyB = 0;
  28.  
  29. // Game Variables
  30. const int  frameSkip     =  1;
  31. int        frameLimit    = frameSkip;
  32. const int  maxLength     = 250;
  33. const int  screenScale   =  4;
  34. const int  screenColumns = screenWidth / screenScale;
  35. const int  screenRows    = screenHeight / screenScale;
  36. bool       buttonState   = false;
  37. bool       gameOver      = true;
  38. bool       firstGame     = true;
  39. int        score         =  0;
  40.  
  41. class D2Point {
  42.     public:
  43.         int x;
  44.         int y;
  45. };
  46.  
  47. class Snake {
  48. public:
  49.     Snake();
  50.     ~Snake();
  51.  
  52.     int velocityX;
  53.     int velocityY;
  54.     int length;
  55.     D2Point position[maxLength];
  56.  
  57.     void reset();
  58.     void grow();
  59.     void move();
  60.     void draw();
  61.  
  62.     void left() { velocityX = -1; velocityY = 0; };
  63.     void right() { velocityX = 1; velocityY = 0; };
  64.     void up() { velocityX = 0; velocityY = -1; };
  65.     void down() { velocityX = 0; velocityY = 1; };
  66.  
  67. private:
  68.  
  69. };
  70.  
  71. class Food {
  72. public:
  73.     Food();
  74.     ~Food();
  75.  
  76.     D2Point position;
  77.  
  78.     void place();
  79.     void draw();
  80. };
  81.  
  82. class Game {
  83.     public:
  84.         void draw();
  85.         void draw(Snake &s, Food &f);
  86. };
  87.  
  88. void Game::draw() {
  89.     u8g2.firstPage();
  90.     do {
  91.         u8g2.setFont(u8g2_font_5x7_tf); // choose a suitable font
  92.                 if (!firstGame) {
  93.             u8g2.drawStr(40, 14, "Game Over");
  94.             u8g2.drawStr(40, 54, "Score:");
  95.             u8g2.setCursor(75, 54);
  96.             u8g2.print(score);
  97.         }
  98.         u8g2.drawStr(50, 24, "Snake");
  99.         u8g2.drawStr(34, 34, "Press Button");
  100.     } while (u8g2.nextPage());
  101. }
  102.  
  103. void Game::draw(Snake &s, Food &f) {
  104.     u8g2.firstPage();
  105.     do {
  106.         /* all graphics commands have to appear within the loop body. */
  107.         u8g2.setFont(u8g2_font_5x7_tf); // choose a suitable font
  108.         s.draw();
  109.         f.draw();
  110.     } while (u8g2.nextPage());
  111. }
  112.  
  113. Snake::Snake() {
  114.     velocityX =  0;
  115.     velocityY = -1;
  116.  
  117.     length = 0;
  118.  
  119.     position[0].x = screenColumns / 2 * screenScale;
  120.     position[0].y = screenRows / 2 * screenScale;
  121. }
  122.  
  123. Snake::~Snake() {
  124.  
  125. }
  126.  
  127. void Snake::reset() {
  128.     length = 0;
  129.     position[0].x = screenColumns / 2 * screenScale;
  130.     position[0].y = screenRows / 2 * screenScale;
  131.     velocityX =  0;
  132.     velocityY = -1;
  133. }
  134.  
  135. void Snake::grow() {
  136.     if ( length < (maxLength - 2 ) ) {
  137.         length++;
  138.     }
  139. }
  140.  
  141. void Snake::move() {
  142.     for (int i = length; i >= 0; i--) {
  143.             position[i + 1].x = position[i].x;
  144.             position[i + 1].y = position[i].y;
  145.     }
  146.  
  147.     position[0].x = position[0].x + (velocityX * screenScale);
  148.     position[0].y = position[0].y + (velocityY * screenScale);
  149. }
  150.  
  151. void Snake::draw() {
  152.     for (int i = length; i >= 0; i--) {
  153.         u8g2.drawBox(position[i].x, position[i].y, screenScale, screenScale);
  154.     }
  155. }
  156.  
  157. Food::Food() {
  158.  
  159. }
  160.  
  161. Food::~Food() {
  162.  
  163. }
  164.  
  165. void Food::place() {
  166.     position.x = random(screenColumns) * screenScale;
  167.     position.y = random(screenRows)    * screenScale;
  168. }
  169.  
  170. void Food::draw() {
  171.     u8g2.drawBox(position.x, position.y, screenScale, screenScale);
  172. }
  173.  
  174. Game game;
  175. Snake snake;
  176. Food food;
  177.  
  178. // The setup function runs once when you press reset or power the board
  179. void setup() {
  180.     u8g2.begin();
  181.  
  182.     pinMode(xAxisPin, INPUT);
  183.     pinMode(yAxisPin, INPUT);
  184.     pinMode(buttonPin, INPUT_PULLUP);
  185.     pinMode(speakerPin, OUTPUT);
  186.  
  187.     randomSeed(analogRead(floatingPin));
  188.  
  189.     food.place();
  190.  
  191.     Serial.begin(115200);
  192. }
  193.  
  194. // The loop function runs over and over again until power down or reset
  195. void loop() {
  196.     // gameOver separates the game into two states; running and attract
  197.     if (!gameOver) {
  198.         // Running state
  199.         frameLimit--;
  200.         if (frameLimit < 1) {
  201.             frameLimit = frameSkip;
  202.  
  203.             joyX = analogRead(xAxisPin);
  204.             joyY = analogRead(yAxisPin);
  205.             joyB = digitalRead(buttonPin);
  206.  
  207.             // Test buttonState. If joyB is HIGH the button is not pressed
  208.             if (joyB) {
  209.                 buttonState = false;
  210.             }
  211.             else {
  212.                 buttonState = true;
  213.             }
  214.  
  215.             if ((joyX < 255) && (snake.velocityX == 0)) {
  216.                 snake.left();
  217.             }
  218.             else if ((joyX > 767) && (snake.velocityX == 0)) {
  219.                 snake.right();
  220.             }
  221.             else if ((joyY < 255) && (snake.velocityY == 0)) {
  222.                 snake.up();
  223.             }
  224.             else if ((joyY > 767) && (snake.velocityY == 0)) {
  225.                 snake.down();
  226.             }
  227.  
  228.             if ( snake.position[0].x < 0 || snake.position[0].x > 127 || snake.position[0].y < 0 || snake.position[0].y > 63 ) {
  229.                 gameOver = true;
  230.                 beep(250);
  231.             }
  232.  
  233.             for (int i = 1; i <= snake.length; i++) {
  234.                 if ((snake.position[0].x == snake.position[i].x) && (snake.position[0].y == snake.position[i].y)) {
  235.                     gameOver = true;
  236.                     beep(250);
  237.                 }
  238.             }
  239.  
  240.             if ((snake.position[0].x == food.position.x) && (snake.position[0].y == food.position.y)) {
  241.                 snake.grow();
  242.                 food.place();
  243.                 score++;
  244.                 beep(50);
  245.             }
  246.  
  247.             if (!gameOver) {
  248.                 snake.move();
  249.             }
  250.  
  251.             // Print out joystick information to serial out
  252.             print_status(joyX, joyY, joyB);
  253.  
  254.         }
  255.  
  256.         game.draw(snake, food);
  257.     }
  258.     else {
  259.         // Attract state
  260.         game.draw();
  261.  
  262.         joyB = digitalRead(buttonPin);
  263.  
  264.         // Test buttonState. If joyB is HIGH the button is not pressed
  265.         if (joyB) {
  266.             buttonState = false;
  267.         }
  268.         else {
  269.             buttonState = true;
  270.         }
  271.  
  272.         if (buttonState) {
  273.             gameOver = false;
  274.             firstGame = false;
  275.             snake.reset();
  276.             score = 0;
  277.             beep(100);
  278.         }
  279.     }
  280.  
  281.     // Transfer internal memory to the display
  282.     //u8g2.sendBuffer();
  283.  
  284.     // General Delay
  285.     //delay(100);
  286. }
  287.  
  288. void beep(int timeout) {
  289.     digitalWrite(speakerPin, HIGH);
  290.     delay(timeout);
  291.     digitalWrite(speakerPin, LOW);
  292. }
  293.  
  294. void print_status(int x, int y, int b) {
  295.     //Serial.print("label");
  296.     //Serial.print(variable);
  297.     //Serial.print(", ");
  298.     //Serial.print("label");
  299.     //Serial.print(variable);
  300.     //Serial.print(", ");
  301.     Serial.print("X: ");
  302.     Serial.print(x);
  303.     Serial.print(", ");
  304.     Serial.print("Y: ");
  305.     Serial.print(y);
  306.     Serial.print(", ");
  307.     Serial.print("B: ");
  308.     Serial.println(b);
  309. }
RAW Paste Data