Arduino TFT 触摸屏复刻 Flappy Bird 游戏完整教程
项目概述
基于 Arduino 与 TFT 触摸屏(如 3.2" SSD1289)复刻经典手游《Flappy Bird》。点击屏幕控制小鸟跳跃,躲避随机高度的移动柱子,分数越高速度越快,最高分掉电保存(EEPROM)。适合进阶学习图形编程、触摸交互与游戏逻辑。

硬件与库准备
- Arduino Mega / Uno(建议 Mega,引脚更多)
- 3.2" TFT 触摸屏模块(SSD1289 驱动,或兼容型号)
- 库文件:UTFT、URTouch(Henning Karlsen 开发)
- 标准库:
EEPROM.h
核心代码架构解析
初始化与对象创建
#include <UTFT.h>
#include <URTouch.h>
#include <EEPROM.h>
// 根据屏幕型号调整参数
UTFT myGLCD(SSD1289, 38, 39, 40, 41);
URTouch myTouch(6, 5, 4, 3, 2);
extern uint8_t SmallFont[];
extern uint8_t BigFont[];
extern uint8_t SevenSegNumFont[];
extern unsigned int bird01[0x41A]; // 小鸟位图数组
// 游戏变量
int xP = 319, yP = 100; // 柱子位置
int yB = 50; // 小鸟 Y 坐标
int movingRate = 3; // 柱子移动速度
float fallRate = 0; // 下落加速度
int fallRateInt = 0;
int score = 0, lastSpeedUpScore = 0, highestScore;
bool screenPressed = false, gameStarted = false;
void setup() {
myGLCD.InitLCD(); myGLCD.clrScr();
myTouch.InitTouch(); myTouch.setPrecision(PREC_MEDIUM);
highestScore = EEPROM.read(0); // 读取最高分
initiateGame();
}
游戏初始化界面 initiateGame()
绘制蓝天背景、绿地、分数栏、最高分、提示文字,调用 drawBird() 绘制小鸟。进入 while(!gameStarted) 循环等待触摸:点击右上角 "RESET" 清零最高分,点击其余区域开始游戏。

主循环 loop() 逻辑
- 柱子移动:
xP -= movingRate,超出屏幕左侧(xP <= -51)重置xP=319、随机yP、分数+1。 - 重力模拟:
fallRate += 0.4,yB += int(fallRate)实现加速下落。 - 碰撞检测:触顶/地、柱子上下缺口判定,触发
gameOver()。 - 触摸控制:检测到触摸且非长按时
fallRate = -6(向上跳跃),防止长按作弊。 - 难度递增:每得 5 分
movingRate++。
避免闪屏的绘图策略
TFT 刷新率低,全屏重绘会闪烁。采用脏矩形/增量绘制:
drawPillars():仅在柱子新旧位置绘制/擦除矩形,配合蓝色背景色覆盖残影。drawBird():绘制位图后,在鸟上方和下方各画一小蓝色圆角矩形擦除残影。


核心自定义函数
// 绘制柱子(增量更新)
void drawPillars(int x, int y) {
if (x >= 270) { /* 屏幕右侧初始化绘制 */ }
else {
// 右侧擦除蓝条
myGLCD.setColor(114,198,206); myGLCD.fillRect(x+51, 0, x+60, y);
// 柱子本体
myGLCD.setColor(0,200,20); myGLCD.fillRect(x+49, 1, x+1, y-1);
myGLCD.setColor(0,0,0); myGLCD.drawRect(x+50, 0, x, y);
// 左侧擦除蓝条
myGLCD.setColor(114,198,206); myGLCD.fillRect(x-1, 0, x-3, y);
// 下柱子同上,y+80 为缺口起始
...
}
// 绘制分数
myGLCD.setColor(0,0,0); myGLCD.setBackColor(221,216,148);
myGLCD.setFont(BigFont); myGLCD.printNumI(score, 100, 220);
}
// 绘制小鸟(位图+残影擦除)
void drawBird(int y) {
myGLCD.drawBitmap(50, y, 35, 30, bird01);
myGLCD.setColor(114,198,206);
myGLCD.fillRoundRect(50, y, 85, y-6); // 上擦除
myGLCD.fillRoundRect(50, y+30, 85, y+36); // 下擦除
}
// 游戏结束处理
void gameOver() {
delay(1000); myGLCD.clrScr();
myGLCD.setColor(255,255,255); myGLCD.setBackColor(0,0,0);
myGLCD.setFont(BigFont);
myGLCD.print("GAME OVER", CENTER, 40);
myGLCD.print("Score:", 100, 80); myGLCD.printNumI(score, 200, 80);
myGLCD.print("Restarting...", CENTER, 120);
// 倒计时 3,2,1
myGLCD.setFont(SevenSegNumFont);
myGLCD.printNumI(3, CENTER, 150); delay(1000);
myGLCD.printNumI(2, CENTER, 150); delay(1000);
myGLCD.printNumI(1, CENTER, 150); delay(1000);
// 更新最高分
if (score > highestScore) { highestScore = score; EEPROM.write(0, highestScore); }
// 重置变量
xP=319; yB=50; fallRate=0; score=0; lastSpeedUpScore=0; movingRate=3; gameStarted=false;
initiateGame();
}
完整代码下载
文末提供完整 sketch、小鸟位图数组文件(bird01.c)打包下载。将 .c 文件置于 sketch 同目录即可编译。
常见问题与优化建议
- 屏幕型号适配:
UTFT myGLCD(...)参数须与你的驱动芯片、引脚一致。 - 触摸校准:若点击偏移,运行 URTouch 例程
Calibration获取校准参数。 - 位图转换:用
ImageConverter565将图片转为.c数组,声明为extern unsigned int bird01[0x41A];。 - 性能瓶颈:若帧率过低,可减少
delay()、简化擦除区域、或升级 ESP32/Teensy 配合更快驱动库。
代码逻辑清晰,适合作为 Arduino 图形游戏开发的入门范例。动手试做吧,祝你最高分破纪录!
制造工艺
- 用 Arduino 打造绚丽显示器 Ambilight 系统
- 用 Arduino UNO 和 OLED 显示屏制作经典 Pong 游戏:分步教程
- DIY Arduino USB 游戏手柄 — 自制高性能游戏手柄
- Arduino 触控打砖块:在 2.4 英寸 TFT LCD 上重现经典街机
- 自制巨型乐高迷你人偶动画操作游戏:Arduino 控制舵机与音效
- Arduino 音频频率检测:基于 FFT 测量最响亮声音峰值
- Arduino 井字棋游戏:MAX7219 点阵屏 + 纸板外壳 DIY
- 使用 SparkFun 7 段数码管构建可靠的 Arduino 倒计时器
- Pixel Chaser:Arduino Nano 单键 NeoPixel 追逐小游戏
- 自制 Arduino 遥控保时捷赛车:从改装底盘到手机 App 控制全攻略
- DIY LED 轮盘赌游戏机 —— Arduino Nano 打造单人桌面街机
- 低成本 Arduino 闪电探测器制作指南