Search This Blog

Saturday, 4 January 2025

DIY Game Console Using SSD1306 OLED Display and NodeMCU/Arduino UNO



DIY Game Console Using OLED Display and NodeMCU/Arduino UNO

Have you ever wondered if you could create your own handheld game console? In this project, I built a compact and functional game console using a 0.96-inch OLED display and a NodeMCU or Arduino UNO. This console is not only a fun project but also a great way to dive into game development and hardware programming.



Project Highlights

  1. Hardware Features:

    • Display: A crisp, 0.96-inch OLED display that brings the game graphics to life.
    • Controller: Designed with buttons for user input, providing a classic gaming feel.
    • Microcontroller: Choose between NodeMCU for Wi-Fi capabilities or Arduino UNO for a simpler setup.
  2. Software Development:

    • Programmed with libraries for handling the OLED display and managing game logic.
    • Simple, retro-style games developed to showcase the console's capabilities.
  3. Applications:

    • Learn about display handling, game logic, and embedded systems.
    • Expandable to include more games or additional features.


Challenges and Learnings

During this project, I explored handling small displays, optimizing microcontroller performance, and balancing functionality with hardware constraints. It’s a rewarding experience for anyone interested in IoT, game development, or Arduino programming.



Why You Should Try It

This project is perfect for hobbyists, makers, or students wanting to combine creativity and technology. With affordable components and endless customization options, you can make it uniquely yours.



Components Required

  • NodeMCU or Arduino UNO Microcontroller
  • 4 Push Buttons
  • Tools like Soldering Iron, Hot Glue Gun
  • OLED 0.96 inch I2C Display


Circuit diagram

This is Circuit Diagram for this project, I used TinkerCAD to make this diagram, so SSD1306 OLED Display was not available, that's why I used 16x2 i2c Display, because these both display is using same communication method which is I2C communication.
So you can replace 16x2 display connections with your 0.96 inch OLED Display.



Upload the Code

#define SSD1306_I2C_ADDRESS 0x3C

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

// OLED display size
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1  // Reset pin not used

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// Button pins
#define UP_BUTTON 00
#define LEFT_BUTTON 14
#define DOWN_BUTTON 13
#define RIGHT_BUTTON 12

// Snake parameters
#define MAX_LENGTH 100
int snakeX[MAX_LENGTH];
int snakeY[MAX_LENGTH];
int snakeLength = 5;
int foodX, foodY;

// Movement direction
int directionX = 1;
int directionY = 0;

// Game state
bool gameOver = false;

// Debounce variables
unsigned long lastDebounceTime = 0;
const unsigned long debounceDelay = 50; // 50ms debounce delay

void setup() {
  // Initialize buttons as inputs with internal pull-up resistors
  pinMode(UP_BUTTON, INPUT_PULLUP);
  pinMode(LEFT_BUTTON, INPUT_PULLUP);
  pinMode(DOWN_BUTTON, INPUT_PULLUP);
  pinMode(RIGHT_BUTTON, INPUT_PULLUP);

  // Initialize display
  if (!display.begin(SSD1306_I2C_ADDRESS, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    for (;;);
  }
  display.clearDisplay();

  // Initialize snake position
  for (int i = 0; i < snakeLength; i++) {
    snakeX[i] = 64 - i;
    snakeY[i] = 32;
  }

  // Place initial food
  placeFood();
}

void loop() {
  if (gameOver) {
    showGameOver();
    return;
  }

  // Handle button presses with debounce
  handleButtonPress();

  // Move the snake
  moveSnake();

  // Check for collisions
  checkCollision();

  // Update display
  drawGame();

  // Delay for game speed
  delay(200);
}

void placeFood() {
  foodX = random(0, SCREEN_WIDTH / 4) * 4;
  foodY = random(0, SCREEN_HEIGHT / 4) * 4;
}

void moveSnake() {
  // Move body
  for (int i = snakeLength - 1; i > 0; i--) {
    snakeX[i] = snakeX[i - 1];
    snakeY[i] = snakeY[i - 1];
  }

  // Move head
  snakeX[0] += directionX * 4;
  snakeY[0] += directionY * 4;

  // Check if food is eaten
  if (snakeX[0] == foodX && snakeY[0] == foodY) {
    if (snakeLength < MAX_LENGTH) {
      snakeLength++;
    }
    placeFood();
  }
}

void checkCollision() {
  // Check wall collision
  if (snakeX[0] < 0 || snakeX[0] >= SCREEN_WIDTH || snakeY[0] < 0 || snakeY[0] >= SCREEN_HEIGHT) {
    gameOver = true;
  }

  // Check self-collision
  for (int i = 1; i < snakeLength; i++) {
    if (snakeX[0] == snakeX[i] && snakeY[0] == snakeY[i]) {
      gameOver = true;
      break;
    }
  }
}

void handleButtonPress() {
  unsigned long currentTime = millis();

  // Check UP button
  if (digitalRead(UP_BUTTON) == LOW && currentTime - lastDebounceTime > debounceDelay && directionY == 0) {
    directionX = 0;
    directionY = -1;
    lastDebounceTime = currentTime;
   
  }
  // Check LEFT button
  else if (digitalRead(LEFT_BUTTON) == LOW && currentTime - lastDebounceTime > debounceDelay && directionX == 0) {
    directionX = -1;
    directionY = 0;
    lastDebounceTime = currentTime;
  }
  // Check DOWN button
  else if (digitalRead(DOWN_BUTTON) == LOW && currentTime - lastDebounceTime > debounceDelay && directionY == 0) {
    directionX = 0;
    directionY = 1;
    lastDebounceTime = currentTime;
  }
  // Check RIGHT button
  else if (digitalRead(RIGHT_BUTTON) == LOW && currentTime - lastDebounceTime > debounceDelay && directionX == 0) {
    directionX = 1;
    directionY = 0;
    lastDebounceTime = currentTime;
  }

  else {
    pinMode(UP_BUTTON, INPUT_PULLUP);
  }
}

void drawGame() {
  display.clearDisplay();

  // Draw the snake
  for (int i = 0; i < snakeLength; i++) {
    display.fillRect(snakeX[i], snakeY[i], 4, 4, SSD1306_WHITE);
  }

  // Draw the food
  display.fillRect(foodX, foodY, 4, 4, SSD1306_WHITE);

  // Show the updated screen
  display.display();
}

void showGameOver() {
  display.clearDisplay();
  display.setTextSize(2);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(10, 25);
  display.println("Game Over!");
  display.display();
  while (true); // Stop the game
}

This is the code you can copy and paste if you used same button and display connections. If you changed the pin connection, you can change this code from line 14 - 18

// Button pins
#define UP_BUTTON 00
#define LEFT_BUTTON 14
#define DOWN_BUTTON 13
#define RIGHT_BUTTON 12


YOU CAN WATCH THIS VIDEO -



 https://youtu.be/cTQhhXtyOdo


This project showcases how simple components like an OLED display and a microcontroller can come together to create something amazing. The possibilities are endless, and the journey of learning and building is the most exciting part. Happy making!

No comments:

Post a Comment

DIY Game Console Using SSD1306 OLED Display and NodeMCU/Arduino UNO

DIY Game Console Using OLED Display and NodeMCU/Arduino UNO Have you ever wondered if you could create your own handheld game console? In th...