픽셀 체이서: 아두이노 나노로 만든 인터랙티브 원탭 LED 게임
부품 및 소모품
| Arduino Nano R3 |
1개 |
| Adafruit NeoPixel 링: WS2812 5050 RGB LED |
1개 |
| 납땜리스 브레드보드 하프 사이즈 |
1개 |
| 10k옴 저항 |
1개 |
| SparkFun 푸시버튼 스위치 12mm |
1개 |
| 점퍼 와이어 (범용) |
1세트 |
앱 및 온라인 서비스
프로젝트 개요
과거 게임 개발자였고, 모바일 게임 개발의 성배 중 하나가 궁극의 "원탭(한 번 탭)" 게임 만들기입니다.
마이크로컨트롤러, 버튼, 시각적 피드백만으로 멋진 원클릭 "물리" 게임을 만들 수 있는지 확인해보고 싶었습니다.
PIXEL CHASER(픽셀 체이서) 소개!
꽤 쉬운 제작이라 바로 시작해봅시다!
필요한 부품은?
- Arduino Nano (또는 사용 가능한 IO 핀 2개 있는 아무 마이크로컨트롤러)
- RGB "NeoPixel" 링 또는 스트립
- 모멘터리 버튼
- 10k 저항
- 브레드보드
- 와이어
1단계
나노를 브레드보드 한 쪽 끝에 USB 커넥터가 가장자리에 오게 꽂습니다.
2단계
버튼을 브레드보드 반대쪽 끝, 가장자리 가까이에 꽂아 누르기 쉽게 합니다.
3단계
버튼 한 쪽과 브레드보드 GND 레일 사이에 10k 저항 연결. 이게 버튼의 기본 LOW 상태. 버튼 눌렀을 때 VCC와 GND 사이 쇼트 방지용(마이크로컨트롤러 등 부품 손상 예방).
4단계
버튼 반대쪽에서 VCC 레일로 점퍼 와이어 연결. 버튼 누르면 High 됨.
5단계
버튼 GND 쪽에서 나노 D3로 점퍼 와이어 연결. D3 읽어 버튼 상태 판단.
6단계
RGB 스트립/링을 브레드보드에 연결. VCC 와이어 → VCC 레일, GND 와이어 → GND 레일, DI(Data In) 와이어 → 나노 D4. D4로 픽셀 제어.
7단계
나노 5V 핀 → VCC 레일, 나노 GND 핀 → GND 레일 점퍼 와이어 연결.
8단계
코드 업로드하고 플레이!
이 프로젝트 즐기셨길 바랍니다!
내 유튜브 채널에서 이런 재미난 프로젝트 더 보실 수 있습니다.
팔로우:
- https://twitter.com/unexpectedmaker
- https://www.facebook.com/unexpectedmaker/
- https://www.instagram.com/unexpectedmaker/
- https://www.patreon.com/unexpectedmaker
- https://www.tindie.com/stores/seonr/
코드
- Pixel Chaser Game - Arduino Code
Pixel Chaser Game - Arduino Code (Arduino)
/* ---------------------------------------------------------------------------
Pixel Chaser Game - v1.0.0 - 24/03/2019.
AUTHOR/LICENSE: Created by Seon Rozenblum - seon@unexpectedmaker.com
Copyright 2016 License: GNU GPL v3 https://www.gnu.org/licenses/gpl-3.0.html
LINKS: Blog: unexpectedmaker.com YOUTUBE: youtube.com/c/unexpectedmaker
DISCLAIMER: This software is furnished "as is", without technical support,
and with no warranty, express or implied, as to its usefulness for any purpose.
PURPOSE: This controller is the software that runs on the Reflow Master
toaster oven controller made by Unexpected Maker
HISTORY: 24/03/2019 v1.0.0 - Initial release.
NOTE: This is a work in progress...
--------------------------------------------------------------------------- */
#include <Adafruit_NeoPixel.h>
#include "OneButton.h"
#define PIXELPIN 4
#define NUMPIXELS 24
#define BUTTON_TAP 3
OneButton buttonTAP(BUTTON_TAP, false);
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIXELPIN, NEO_GRB + NEO_KHZ800);
int playerIndex = -1;
int playerIndexTrail = -1;
int playerDirection = 1;
float nextMove = 0;
float currentPlayerSpeed = 150;
unsigned long countdown = 0;
int enemyIndex = -1;
int coinIndex = -1;
int score = 0;
int bestScore = 0;
int lastScore = 0;
bool gameOver = false;
void setup() {
pinMode(BUTTON_TAP, INPUT);
buttonTAP.attachClick(singleClick);
buttonTAP.attachLongPressStart(longClick);
pixels.begin();
pixels.setBrightness(20);
countdown = millis() + 2000;
}
void loop() {
buttonTAP.tick();
if (gameOver) return;
SetLevel();
if (countdown > millis()) {
pixels.show();
return;
}
DisplayPlayer();
pixels.show();
}
void ClearLevel() {
for(int i=0; i= 0) pixels.setPixelColor(playerIndexTrail, pixels.Color(0,0,0));
if (playerIndex >= 0) {
pixels.setPixelColor(playerIndex, pixels.Color(0,100,0));
playerIndexTrail = playerIndex;
}
playerIndex += playerDirection;
if (playerIndex < 0) playerIndex = NUMPIXELS - 1;
else if (playerIndex == NUMPIXELS) playerIndex = 0;
pixels.setPixelColor(playerIndex, pixels.Color(0,255,0));
if (playerIndex == coinIndex) {
enemyIndex = -1; coinIndex = -1; score++;
currentPlayerSpeed = constrain(currentPlayerSpeed - 10, 50, 150);
ClearLevel();
pixels.setPixelColor(playerIndex, pixels.Color(0,255,0));
} else if (playerIndex == enemyIndex) {
lastScore = score;
if (score >= bestScore) bestScore = score;
GameOver();
gameOver = true;
enemyIndex = -1; coinIndex = -1; playerIndex = -1;
}
}
}
void singleClick() {
if (countdown > millis()) return;
playerDirection = -playerDirection;
}
void longClick() {
gameOver = !gameOver;
if (gameOver) {
enemyIndex = -1; coinIndex = -1; playerIndex = -1;
currentPlayerSpeed = 150; ClearLevel();
} else {
ClearLevel(); score = 0; currentPlayerSpeed = 150;
countdown = millis() + 2000;
}
}