Pixel Chaser:Arduino Nano 单键 NeoPixel 追逐小游戏
项目简介
作为一名前游戏开发者,我一直想在微控制器上实现一个"单键物理游戏"。Pixel Chaser 诞生了:只需一个按钮、一个 NeoPixel 环、一块 Arduino Nano,即可体验反应速度与策略的微型街机游戏。
游戏规则
- 绿色像素 = 玩家,自动沿环顺/逆时针移动
- 红色像素 = 敌人,固定位置(吃到金币后重新随机)
- 黄色像素 = 金币,位于玩家与敌人之间
- 单击按钮:反转移动方向
- 长按按钮:开始新游戏 / 结束当前游戏
- 吃到金币:得分+1,速度加快(最快 50ms/步),敌人和金币重置位置
- 撞到敌人:游戏结束,显示最高分(黄)与本局分(红)
硬件清单
| 组件 | 数量 | 备注 |
|---|---|---|
| Arduino Nano R3 | 1 | 或任意 2 空闲 IO 的 MCU |
| NeoPixel 环/条 (WS2812) | 1 | 代码默认 24 颗,可改 NUMPIXELS |
| 轻触按钮 | 1 | 12mm 方头 |
| 10kΩ 电阻 | 1 | 按钮下拉 |
| 半尺寸面包板 + 跳线 | 若干 |
接线指南(8 步完成)
- Nano 插面包板一端,USB 口朝外
- 按钮插另一端边缘,便于拇指操作
- 10kΩ 电阻接按钮一脚 → GND 轨(下拉)
- 按钮另一脚 → VCC 轨(按下拉高)
- 按钮 GND 侧同一节点 → Nano D3(读取状态)
- NeoPixel:VCC→VCC 轨,GND→GND 轨,DI→Nano D4
- Nano 5V→VCC 轨,GND→GND 轨
- 上传代码,玩!

代码架构亮点
- 使用
OneButton库处理单击/长按/消抖 - 状态机设计:
gameOver、countdown、playerIndex、enemyIndex、coinIndex - 非阻塞主循环:
nextMove控制移动节奏,buttonTAP.tick()轮询按钮 - 视觉反馈:玩家留尾迹(暗绿),当前位置亮绿;游戏结束红色扩散动画
- 难度自适应:
currentPlayerSpeed = constrain(speed - 10, 50, 150)
完整代码
/* Pixel Chaser Game - v1.0.0
* Author: Seon Rozenblum (unexpectedmaker.com)
* License: GNU GPL v3
*/
#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, playerIndexTrail = -1, playerDirection = 1;
float nextMove = 0, currentPlayerSpeed = 150;
unsigned long countdown = 0;
int enemyIndex = -1, coinIndex = -1;
int score = 0, bestScore = 0, 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, 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 = 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 = coinIndex = playerIndex = -1;
}
}
}
void singleClick() { if (countdown > millis()) return; playerDirection = -playerDirection; }
void longClick() {
gameOver = !gameOver;
if (gameOver) { enemyIndex = coinIndex = playerIndex = -1; currentPlayerSpeed = 150; ClearLevel(); }
else { ClearLevel(); score = 0; currentPlayerSpeed = 150; countdown = millis() + 2000; }
}
扩展思路
- 增加多种敌人类型(移动、分裂)
- 加入音效(蜂鸣器配合吃币/撞击/加速)
- 做成 PCB 手柄外形,配合 3D 打印外壳成成品玩具
- 移植到 ESP32 增加蓝牙对战/排行榜
作者链接
- 博客:unexpectedmaker.com
- YouTube:Unexpected Maker
- GitHub/Tindie/Patreon 同名
制造工艺
- Arduino Nano 与 MPU-6050 构建实时陀螺仪游戏
- Arduino 数字骰子:LCD 显示随机点数的电子骰子
- 用 Arduino UNO 和 OLED 显示屏制作经典 Pong 游戏:分步教程
- 用 Arduino Nano 自制 37 灯珠轮盘赌游戏机
- DIY Arduino USB 游戏手柄 — 自制高性能游戏手柄
- Arduino 触控打砖块:在 2.4 英寸 TFT LCD 上重现经典街机
- 自制 16×8 LED 矩阵俄罗斯方块游戏机:Arduino Nano + 74HC595 驱动
- Arduino 简易排斥式磁悬浮:电路与 DIY 指南
- Arduino 自动化 Chrome 恐龙游戏 - LDR 光敏电阻 + Python 实现全自动跳跃
- Alexa 语音控制 Arduino 智能家居中枢:基于 Yun + PubNub + AWS Lambda 全栈实现
- Arduino Nano 驱动 NeoPixel 矩阵:自制霓虹乒乓游戏
- Arduino Nano 与 WS2812 灯带打造 1D 乒乓球游戏——分步 DIY 教程