산업 제조
산업용 사물 인터넷 | 산업자재 | 장비 유지 보수 및 수리 | 산업 프로그래밍 |
home  MfgRobots >> 산업 제조 >  >> Manufacturing Technology >> 제조공정

아두이노 8x8 LED 매트릭스 뱀 게임 만들기

부품 및 소모품

아두이노 프로토 실드 1개
아두이노 우노 (Arduino UNO) 1개
아날로그 조이스틱 (일반형) 1개
수/암 점퍼 와이어 1세트
8x8 LED 매트릭스 (단색, SparkFun LED Array) 1개

앱 및 온라인 서비스

아두이노 IDE 링크

프로젝트 개요

메카노이드와 이렉터 세트 프레임으로 게임 콘솔을 만들고, Sergey Royz의 코드(꼭 확인해보세요)를 기반으로 속도 조절 등을 추가해 부드럽게 동작하도록 개선했습니다. 프레임 제작 방법은 생략하니 직접 만드시길 권장합니다. 재미있게 즐기세요! 질문이나 다음 프로젝트 추천은 댓글로 남겨주세요. 프리칭이 작동하지 않아 배선은 텍스트로 설명합니다.

회로도

아두이노 우노에 프로토 실드를 장착해 브레드보드 없이 GND와 5V를 추가로 사용합니다.

LED 매트릭스 연결 (MAX7219 기반)

조이스틱 연결

코드

Snake 게임 (C/C++)

아래 코드를 복사해 아두이노 IDE에 붙여넣기만 하면 됩니다.

/**
 * Snake Game
 * 고전 뱀 게임 구현: 뱀이 끊임없이 이동하며 자신과 벽에 부딪히지 않게 조작
 * 먹이를 먹으면 길이가 늘고 속도가 약간 빨라짐
 * 2016년 6월 23일, Sergey Royz & hunter Buzzell
 */
#include <LedControl.h>

/* 조이스틱 핀 */
#define VRX A0
#define VRY A1
#define SW 2

/* 디스플레이 핀 */
#define CLK 8
#define CS 9
#define DIN 10
#define SIZE 8
#define ADVANCE_DELAY 20

int snake[SIZE*SIZE][2];
int length;
int food[2], v[2];
bool is_game_over = false;
long current_time, prev_advance;
int blink_count;
const short messageSpeed = 5;

LedControl lc = LedControl(DIN, CLK, CS, 1);

void init_game() {
  prev_advance = current_time = 0;
  blink_count = 3;
  int half = SIZE / 2;
  length = SIZE / 3;
  for (int i = 0; i < length; i++) {
    snake[i][0] = half - 1;
    snake[i][1] = half + i;
  }
  food[0] = half + 1;
  food[1] = half - 1;
  v[0] = 0; v[1] = -1;
}

void render() {
  for (int i = 0; i < length; i++) {
    lc.setLed(0, snake[i][0], snake[i][1], 1);
  }
  lc.setLed(0, food[0], food[1], 1);
}

void clearScreen() {
  for (int x = 0; x < SIZE; x++)
    for (int y = 0; y < SIZE; y++)
      lc.setLed(0, x, y, 0);
}

/* 뱀을 한 칸 전진, 게임 오버면 true 반환 */
bool advance() {
  int head[2] = {snake[0][0] + v[0], snake[0][1] + v[1]};
  
  // 벽 충돌 체크
  if (head[0] < 0 || head[0] >= SIZE || head[1] < 0 || head[1] >= SIZE) {
    delay(1000); showGameOverMessage(); return true;
  }
  // 자기 몸 충돌 체크
  for (int i = 0; i < length; i++) {
    if (snake[i][0] == head[0] && snake[i][1] == head[1]) {
      delay(1000); showGameOverMessage(); return true;
    }
  }
  
  bool grow = (head[0] == food[0] && head[1] == food[1]);
  if (grow) {
    length++;
    randomSeed(current_time);
    food[0] = random(SIZE);
    food[1] = random(SIZE);
  }
  
  // 몸통 이동
  for (int i = length - 1; i >= 0; i--) {
    snake[i + 1][0] = snake[i][0];
    snake[i + 1][1] = snake[i][1];
  }
  snake[0][0] += v[0];
  snake[0][1] += v[1];
  return false;
}

void setup() {
  pinMode(SW, INPUT_PULLUP);
  pinMode(VRX, INPUT);
  pinMode(VRY, INPUT);
  attachInterrupt(digitalPinToInterrupt(SW), restart, RISING);
  lc.shutdown(0, false);
  lc.setIntensity(0, 8);
  init_game();
  render();
}

void loop() {
  if (!is_game_over) {
    clearScreen();
    render();
    if (current_time - prev_advance > ADVANCE_DELAY) {
      is_game_over = advance();
      prev_advance = current_time;
    }
  } else {
    while (blink_count > 0) {
      clearScreen(); delay(300);
      render(); delay(300);
      blink_count--;
    }
  }
  readControls();
  current_time++;
}

void restart() {
  init_game();
  is_game_over = false;
}

void readControls() {
  int dx = map(analogRead(VRX), 0, 906, 2, -2);
  int dy = map(analogRead(VRY), 0, 906, -2, 2);
  if (dx != 0) dx = dx / abs(dx);
  if (dy != 0) dy = dy / abs(dy);
  if (dy != 0 && v[0] != 0) { v[0] = 0; v[1] = dy; }
  if (dx != 0 && v[1] != 0) { v[0] = dx; v[1] = 0; }
}

/* GAME OVER 메시지 패턴 (PROGMEM 저장) */
const PROGMEM bool gameOverMessage[8][90] = {
  {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,1,1,0,0,0,1,1,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,0,0,0,1,1,0,0,1,1,0,0,1,1,1,1,1,1,0,0,1,1,1,1,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,1,0,1,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,0,0,0,0,1,1,0,0,1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1,0,0,1,1,0,0,1,1,1,1,1,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,0,0,0,0,1,1,0,0,1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1,1,1,1,1,0,0,1,1,0,1,0,1,1,0,0,1,1,1,1,1,0,0,0,0,0,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,1,1,1,0,0,0,1,1,1,1,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0,1,1,0,1,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,0,0,0,1,1,1,1,0,0,0,1,1,0,0,0,0,0,0,1,1,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,1,1,0,0,1,1,0,0,1,1,0,0,0,1,1,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,1,1,0,0,0,0,1,1,1,1,1,1,0,0,1,1,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0}
};

void showGameOverMessage() {
  for (int d = 0; d < sizeof(gameOverMessage[0]) - 7; d++) {
    for (int col = 0; col < 8; col++) {
      delay(messageSpeed);
      for (int row = 0; row < 8; row++) {
        lc.setLed(0, row, col, pgm_read_byte(&(gameOverMessage[row][col + d])));
      }
    }
  }
}

제조공정

  1. DIY 아두이노 USB 게임 컨트롤러 - 나만의 고성능 게임패드 만들기
  2. 아두이노 나노와 MAX7219로 만드는 24x16 LED 퐁 게임 콘솔
  3. 아두이노 나노로 테트리스 게임 만들기: DIY 16×8 LED 매트릭스
  4. 아두이노 블루투스로 LED 제어하기 - HC-05 & MIT App Inventor 입문 가이드
  5. PIR 모션 센서 연동 인터랙티브 LED 매트릭스 도어 디스플레이 - 아두이노 홀리데이 인사
  6. 스마트 아두이노 4족 보행 로봇 제작: 단계별 완벽 가이드
  7. 픽셀 체이서: 아두이노 나노로 만든 인터랙티브 원탭 LED 게임
  8. 아두이노 8×8 LED 매트릭스 플립 시계 – DIY 실시간 시계 프로젝트
  9. 아두이노 RGB LED 컬러 믹서: 입문자 친화적 DIY 프로젝트
  10. 아두이노 우노로 8×8 LED 매트릭스 마스터하기: 단계별 가이드