Differences

This shows you the differences between two versions of the page.

Link to this comparison view

iothings:proiecte:2023:snake_game [2024/01/17 22:27]
eugen.georgescu2202 created
iothings:proiecte:2023:snake_game [2024/01/17 23:27] (current)
eugen.georgescu2202
Line 1: Line 1:
-====== Snake ====== ​+====== Snake ======
  
   * Author: Georgescu Eugen-Robert   * Author: Georgescu Eugen-Robert
Line 5: Line 5:
   * Master: AAC   * Master: AAC
   * Academic year: 2023-2024   * Academic year: 2023-2024
-  * Source files: +  * Source files: ​{{:​iothings:​proiecte:​2023:​snake.rar }}  
- +  * {{:​iothings:​proiecte:​2023:​snake.pptx }}
- +
-====== Introduction ======+
  
 ===== Project Description ===== ===== Project Description =====
Line 20: Line 18:
   * OLED 0.96” Screen: an OLED screen which has a reduced energy consumption,​ only 0.08W. The interface type is IIC;   * OLED 0.96” Screen: an OLED screen which has a reduced energy consumption,​ only 0.08W. The interface type is IIC;
   * Black Biaxial Joystick module with 5 pins: a normal joystick   * Black Biaxial Joystick module with 5 pins: a normal joystick
- Pinout scheme of the ESP32 board +==Pinout scheme of the ESP32 board:==  
-  +{{:​iothings:​proiecte:​2023:​pinout_scheme.jpeg?​700 }}
-{{ :​iothings:​proiecte:​2023:​pinout_scheme.jpeg?​200| }}+
  
-Diagram:  +==Diagram:== 
-{{:​iothings:​proiecte:​2023:​diagram.png?​200|}}+{{:​iothings:​proiecte:​2023:​diagram.png?​400 }}
    
-Real life: +==Real life:== 
-{{:​iothings:​proiecte:​2023:​real_life_view.jpeg?​200|}}+{{:​iothings:​proiecte:​2023:​real_life_view.jpeg?​500 }}
    
-Function used on this project +===== Function used on this project ​===== 
-Setup function+=== Setup function ​===
 This function was used to start the display and clear it, and after that to initialize the snake and set its color to white. This function was used to start the display and clear it, and after that to initialize the snake and set its color to white.
-{{:​iothings:​proiecte:​2023:​setup_function.png?200|}}+<​code>​ 
 +void setup() ​{ 
 +  Serial.begin(115200);​
  
-Loop function ​+  if (!display.begin(SSD1306_SWITCHCAPVCC,​ OLED_ADDR)) { 
 +    Serial.println(F("​SSD1306 allocation failed"​));​ 
 +    for (;;) 
 +      ; 
 +  } 
 + 
 +  display.clearDisplay();​ // Clear the display buffer 
 + 
 +  // Initialize the snake 
 +  for (int i = snakeSize - 1; i >= 0; i--) { 
 +    snakeX[i] = snakeSize - 1 - i; 
 +    snakeY[i] = 0; 
 +  } 
 + 
 +  // Set text color and size 
 +  display.setTextColor(SSD1306_WHITE);​ 
 +  display.setTextSize(1);​ 
 + 
 +  // Start the game loop 
 +  gameLoop();​ 
 +
 +</​code>​ 
 + 
 +=== Loop function ​===
 Here I update the snake position then I draw it. After the snake is on the screen, I spawn a pixel random on the screen that can be eaten by the snake. Here I update the snake position then I draw it. After the snake is on the screen, I spawn a pixel random on the screen that can be eaten by the snake.
-{{:​iothings:​proiecte:​2023:​loop_function.png?​200|}}+<​code>​ 
 +void gameLoop() ​{ 
 +  while (true) ​{ 
 +    // Update the snake position 
 +    updateSnake();​ 
 + 
 +    // Draw the snake 
 +    drawSnake();​ 
 + 
 +    // Check for joystick input 
 +    checkJoystick();​ 
 + 
 +    // Check if the snake eats the pixel 
 +    if (snakeX[0] == pixelX && snakeY[0] == pixelY) { 
 +      snakeSize++;​ 
 +      spawnPixel();​ // Spawn a new pixel after eating the current one 
 +    } 
 +     
 +    delay(200); 
 +  ​} 
 +} 
 +</​code>​
  
-Update function ​+=== Update function ​===
 On this function I update the entire snake positions (each of the pixels that make the body of the snake). Then I move the head on the direction of the pixel, I get this direction from a function called: checkJoystick. After that, I check if the snake hit the boundaries of the screen to teleport on the other side of the screen. On this function I update the entire snake positions (each of the pixels that make the body of the snake). Then I move the head on the direction of the pixel, I get this direction from a function called: checkJoystick. After that, I check if the snake hit the boundaries of the screen to teleport on the other side of the screen.
-  +<​code>​ 
-{{:iothings:proiecte:2023:update_function.png?​200|}}+void updateSnake() ​{ 
 +    // Update the entire snake'​s position 
 +  for (int i = snakeSize - 1; i > 0; i--) { 
 +    snakeX[i] = snakeX[i - 1]; 
 +    snakeY[i] = snakeY[i - 1]; 
 +  } 
 +   
 +  // Move the head of the snake based on the direction 
 +  switch (direction) { 
 +    case 0// Right 
 +      snakeX[0]++;​ 
 +      break; 
 +    case 1// Down 
 +      snakeY[0]++;​ 
 +      break; 
 +    case 2// Left 
 +      snakeX[0]--;​ 
 +      break; 
 +    case 3// Up 
 +      snakeY[0]--;​ 
 +      break; 
 +  ​} 
 +   
 +  // Check for collisions with the screen boundaries 
 +  if (snakeX[0] >= SCREEN_WIDTH / 8) { 
 +    snakeX[0] = 0; 
 +  } else if (snakeX[0] < 0) { 
 +    snakeX[0] = SCREEN_WIDTH / 8 - 1; 
 +  ​}
  
-DrawSnake function+  if (snakeY[0] >= SCREEN_HEIGHT / 8) { 
 +    snakeY[0] = 0; 
 +  } else if (snakeY[0] < 0) { 
 +    snakeY[0] = SCREEN_HEIGHT / 8 - 1; 
 +  } 
 +  for (int i = 0; i < snakeSize; i++) { 
 +    Serial.println("​Before collision (" + String(snakeX[i]) + ","​ + String(snakeY[i]) + "​)"​);​ 
 +  } 
 +     // Check for collisions with the snake'​s body, excluding the head 
 +  for (int i = 1; i < snakeSize; i++) { 
 +    if (snakeX[0] == snakeX[i] && snakeY[0] == snakeY[i]) { 
 +      // Snake head collided with its body, end the game 
 +      endGame();​ 
 +    } 
 +  } 
 +
 +</​code>​  
 + 
 + 
 +=== DrawSnake function ​===
 Used to draw the snake on the screen. Used to draw the snake on the screen.
-{{:​iothings:​proiecte:​2023:​drawSnake_function.png?200|}}+<​code>​ 
 +void drawSnake() ​{ 
 +  // Clear the display 
 +  display.clearDisplay();​ 
 + 
 +  // Draw the snake 
 +  for (int i = 0; i < snakeSize; i++) { 
 +    display.fillRect(snakeX[i] * 8, snakeY[i] * 8, 8, 8, SSD1306_WHITE);​ 
 +  ​} 
 + 
 +  // Draw the pixel 
 +  display.fillRect(pixelX * 8, pixelY * 8, 8, 8, SSD1306_WHITE);​ 
 + 
 +  // Display the buffer 
 +  display.display();​ 
 +} 
 +</​code>​
    
-checkJoystick function+=== checkJoystick function ​===
 I used this function to check the position of the joystick so I can give the snake the direction that I want it to move to. In this code I also made impossible for the snake to go in the opposite direction of the current one I used this function to check the position of the joystick so I can give the snake the direction that I want it to move to. In this code I also made impossible for the snake to go in the opposite direction of the current one
-{{:​iothings:​proiecte:​2023:​checkJoystick_function.png?​200|}}+<​code>​ 
 +void checkJoystick() ​{ 
 +  int xValue = analogRead(JOYSTICK_X);​ 
 +  int yValue = analogRead(JOYSTICK_Y);​ 
 +  int OK = 0; 
 + 
 +  if (xValue < JOYSTICK_THRESHOLD && lastXValue <= JOYSTICK_THRESHOLD) ​{ 
 +    // Move right 
 +    if (direction != 0 && direction != 2) { 
 +      direction = 0; 
 +      OK = 1; 
 +    } 
 +  } else if (xValue > JOYSTICK_THRESHOLD2 && lastXValue >= -JOYSTICK_THRESHOLD) { 
 +    // Move left 
 +    if (direction != 2 && direction != 0) { 
 +      direction = 2; 
 +      OK = 1; 
 +    } 
 +  } 
 + 
 +  if (yValue < JOYSTICK_THRESHOLD && lastYValue <= JOYSTICK_THRESHOLD && OK == 0) { 
 +    // Move up 
 +    if (direction != 3 && direction != 1) { 
 +      direction = 3; 
 +    } 
 +  } else if (yValue > JOYSTICK_THRESHOLD2 && lastYValue >= -JOYSTICK_THRESHOLD && OK == 0) { 
 +    // Move down 
 +    if (direction != 1 && direction != 3) { 
 +      direction = 1; 
 + 
 +    } 
 +  ​} 
 + 
 +  lastXValue = xValue; 
 +  lastYValue = yValue; 
 +} 
 +</​code>​
    
-Spawnpixel function+=== Spawnpixel function ​===
 I spawn the food of the snake as a pixel random on the screen. I spawn the food of the snake as a pixel random on the screen.
-{{:​iothings:​proiecte:​2023:​Spawnpixel_function.png?​200|}}+<​code>​ 
 +void spawnPixel() ​{ 
 +  // Generate random coordinates for the pixel 
 +  pixelX = random(SCREEN_WIDTH / 8); 
 +  pixelY = random(SCREEN_HEIGHT / 8); 
 + 
 +  // Ensure the pixel does not spawn on the snake 
 +  for (int i = 0; i < snakeSize; i++) { 
 +    while (pixelX == snakeX[i] && pixelY == snakeY[i]) { 
 +      pixelX = random(SCREEN_WIDTH / 8); 
 +      pixelY = random(SCREEN_HEIGHT / 8); 
 +    ​} 
 +  } 
 + 
 +  // Draw the pixel on the display 
 +  display.fillRect(pixelX * 8, pixelY * 8, 8, 8, SSD1306_WHITE);​ 
 +  display.display();​ 
 +} 
 +</​code>​
    
-Endgame function+=== Endgame function ​===
 Print on the screen the GAME OVER message if the snake hit himself. Print on the screen the GAME OVER message if the snake hit himself.
-{{:iothings:​proiecte:​2023:​Endgame_function.png?200|}}+<​code>​ 
 +void endGame() ​{ 
 +  // Add your game-over logic here 
 +      display.clearDisplay();​ 
 +      display.setCursor(8,​8);​ 
 +      display.print("​GAME OVER!"​);​ 
 +      display.display();​ 
 +      delay(5000); ​ // Display "You Lose" for 5 seconds 
 + 
 +  // Print snake coordinates for debugging 
 +  Serial.println("​Snake Coordinates:"); 
 +  for (int i = 0; i < snakeSize; i++) { 
 +    Serial.println("​("​ + String(snakeX[i]) + ","​ + String(snakeY[i]) + "​)"​);​ 
 +  } 
 + 
 +  while (true) { 
 +    // Do nothing 
 +  ​} 
 +} 
 +</​code>​
    
-Rest of the code:+=== Rest of the code ===
 Here I declared the screen and the pins that I used. I also declared 2 THRESHOLDS because when the joystick was on the middle, I constantly get values between 1850 and 1900 and I don’t want that those values to influent the movement. On the end I declared snake characteristics. Here I declared the screen and the pins that I used. I also declared 2 THRESHOLDS because when the joystick was on the middle, I constantly get values between 1850 and 1900 and I don’t want that those values to influent the movement. On the end I declared snake characteristics.
-{{:​iothings:​proiecte:​2023:​rest_of_code.png?​200|}} +<​code>​ 
-The library that I used are: +#define SCREEN_WIDTH 128 
-{{:​iothings:​proiecte:​2023:​library.png?​200|}} +#define SCREEN_HEIGHT 32
-  +
-And mostly I used the for the LCD.+
  
-Conclusion +// Define the I2C address ​for the display 
-As a conclusion ​for the project, I realized a snake game that can be controlled using a joystick. The purpose of the game is to eat as many food as possible and to not touch the rest of the body.+#define OLED_ADDR 0x3C
  
 +Adafruit_SSD1306 display(SCREEN_WIDTH,​ SCREEN_HEIGHT,​ &Wire, OLED_ADDR);
  
 +#define JOYSTICK_X A5
 +#define JOYSTICK_Y A6
 +#define JOYSTICK_THRESHOLD 1800
 +#define JOYSTICK_THRESHOLD2 2000
  
 +int snakeSize = 3;
 +int snakeX[100],​ snakeY[100];​
 +int direction = 0; // 0: right, 1: down, 2: left, 3: up
 +</​code>​
  
  
 +The library that I used are:
 +<​code>​
 +#include <​Wire.h>​
 +#include <​Adafruit_GFX.h>​
 +#include <​Adafruit_SSD1306.h>​
 +</​code>​
 + 
 +And mostly I used the for the LCD.
 +
 +===== Conclusion =====
 +As a conclusion for the project, I realized a snake game that can be controlled using a joystick. The purpose of the game is to eat as many food as possible and to not touch the rest of the body.
  
  
-Bibliography: +===== Bibliography ​===== 
-https://​www.optimusdigital.ro/​ro/​senzori-senzori-de-atingere/​742-modul-joystick-ps2-biaxial-negru-cu-5-pini.html?​search_query=joystick&​results=42 +https://​www.optimusdigital.ro/​ro/​senzori-senzori-de-atingere/​742-modul-joystick-ps2-biaxial-negru-cu-5-pini.html?​search_query=joystick&​results=42 ​\\ 
-https://​cleste.ro/​ecra-oled-0-96-inch.html +https://​cleste.ro/​ecra-oled-0-96-inch.html ​\\ 
-Placă dezvoltare NodeMCU WIFI + Bluetooth ESP32 | Cleste.ro +https://​cleste.ro/​placa-dezvoltare-nodemcu-wifi-bluetooth-esp32.html \\ 
-ESP32 Pinout ReferenceWhich GPIO pins should you use? | Random Nerd Tutorials+https://​randomnerdtutorials.com/​esp32-pinout-reference-gpios/​ \\
 https://​esp32io.com/​tutorials/​esp32-joystick https://​esp32io.com/​tutorials/​esp32-joystick
  
  
iothings/proiecte/2023/snake_game.1705523274.txt.gz · Last modified: 2024/01/17 22:27 by eugen.georgescu2202
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0