고급⏱ 예상 시간: 50분📝 6단계

OLED 미니 게임기

조이스틱으로 OLED 화면 위의 캐릭터를 움직여 장애물을 피하는 간단한 미니 게임을 만듭니다.

🧩 필요한 모듈

Arduino Uno
브레드보드
피에조 부저
조이스틱 모듈
점퍼 와이어
OLED 디스플레이 (0.96인치 I2C)
저항 (220Ω / 10kΩ)

📖 단계별 설명서

📝

1단계준비물 확인

다음 부품들을 준비해주세요:

  • Arduino Uno 1개
  • 브레드보드 1개
  • 점퍼 와이어 10개
  • OLED 디스플레이 (0.96인치 I2C) 1개
  • 조이스틱 모듈 1개
  • 피에조 부저 1개
  • 저항 (필요시)
📝

2단계회로 연결하기

  1. OLED의 SDA를 A4, SCL을 A5에 연결합니다.
  2. OLED의 VCC를 5V, GND를 GND에 연결합니다.
  3. 조이스틱의 VRx를 A0, VRy를 A1에 연결합니다.
  4. 조이스틱의 SW를 D2에 연결합니다 (내장 풀업 사용).
  5. 조이스틱의 +5V를 5V, GND를 GND에 연결합니다.
  6. 부저를 D8에 연결합니다.

📐 회로도

회로도 이미지

/images/projects/oled-game-circuit.png

📝

3단계라이브러리 설치

아두이노 IDE 라이브러리 관리에서:

  • Adafruit SSD1306 설치
  • Adafruit GFX Library 설치
📝

4단계코드 작성하기

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

#define SCREEN_W 128
#define SCREEN_H 64
Adafruit_SSD1306 display(SCREEN_W, SCREEN_H, &Wire, -1);

const int JOY_X = A0;
const int JOY_BTN = 2;
const int BUZZER = 8;

// Player
int playerX = 10;
int playerY = 32;
const int playerSize = 6;

// Obstacles
const int MAX_OBS = 4;
int obsX[MAX_OBS];
int obsY[MAX_OBS];
int obsH[MAX_OBS];
int obsSpeed = 2;

int score = 0;
bool gameOver = false;
unsigned long lastFrame = 0;

void resetGame() {
  playerY = 32;
  score = 0;
  obsSpeed = 2;
  gameOver = false;
  for (int i = 0; i < MAX_OBS; i++) {
    obsX[i] = SCREEN_W + i * 40;
    obsY[i] = random(10, SCREEN_H - 20);
    obsH[i] = random(8, 20);
  }
}

void setup() {
  pinMode(JOY_BTN, INPUT_PULLUP);
  pinMode(BUZZER, OUTPUT);
  
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();
  display.setTextColor(SSD1306_WHITE);
  
  randomSeed(analogRead(A2));
  resetGame();
}

void loop() {
  if (millis() - lastFrame < 33) return;  // ~30fps
  lastFrame = millis();

  if (gameOver) {
    display.clearDisplay();
    display.setTextSize(2);
    display.setCursor(15, 10);
    display.print("GAME OVER");
    display.setTextSize(1);
    display.setCursor(35, 35);
    display.print("Score: ");
    display.print(score);
    display.setCursor(20, 50);
    display.print("Press to restart");
    display.display();

    if (digitalRead(JOY_BTN) == LOW) {
      delay(300);
      resetGame();
    }
    return;
  }

  // Read joystick Y axis
  int joyVal = analogRead(JOY_X);  // Using X for vertical
  if (joyVal < 400) playerY -= 3;
  if (joyVal > 600) playerY += 3;
  playerY = constrain(playerY, 0, SCREEN_H - playerSize);

  // Update obstacles
  for (int i = 0; i < MAX_OBS; i++) {
    obsX[i] -= obsSpeed;
    if (obsX[i] < -10) {
      obsX[i] = SCREEN_W + random(10, 30);
      obsY[i] = random(5, SCREEN_H - 20);
      obsH[i] = random(8, 20);
      score++;
      tone(BUZZER, 2000, 30);

      // Increase speed every 5 points
      if (score % 5 == 0 && obsSpeed < 6) obsSpeed++;
    }

    // Collision detection
    if (obsX[i] < playerX + playerSize &&
        obsX[i] + 6 > playerX &&
        obsY[i] < playerY + playerSize &&
        obsY[i] + obsH[i] > playerY) {
      gameOver = true;
      tone(BUZZER, 200, 500);
    }
  }

  // Draw
  display.clearDisplay();

  // Ground line
  display.drawLine(0, SCREEN_H - 1, SCREEN_W, SCREEN_H - 1, SSD1306_WHITE);

  // Player (square)
  display.fillRect(playerX, playerY, playerSize, playerSize, SSD1306_WHITE);

  // Obstacles
  for (int i = 0; i < MAX_OBS; i++) {
    display.fillRect(obsX[i], obsY[i], 6, obsH[i], SSD1306_WHITE);
  }

  // Score
  display.setTextSize(1);
  display.setCursor(90, 2);
  display.print("S:");
  display.print(score);

  display.display();
}
+110 줄 더 보기
📝

5단계업로드 및 테스트

  1. 코드를 업로드합니다.
  2. 조이스틱을 위아래로 움직여 캐릭터(사각형)를 조종합니다.
  3. 오른쪽에서 다가오는 장애물을 피합니다.
  4. 충돌하면 GAME OVER 화면이 나타납니다.
  5. 조이스틱 버튼을 누르면 재시작합니다.

💡 팁: score가 올라갈수록 속도가 빨라집니다! 최고 점수에 도전해보세요.

📝

6단계심화 — 하이스코어 저장

EEPROM 라이브러리를 사용하면 최고 점수를 저장하여 전원을 꺼도 기록이 유지됩니다.

🎉

축하합니다!

"OLED 미니 게임기" 프로젝트를 완성했습니다!