亿迅智能制造网
工业4.0先进制造技术信息网站!
首页 | 制造技术 | 制造设备 | 工业物联网 | 工业材料 | 设备保养维修 | 工业编程 |
home  MfgRobots >> 亿迅智能制造网 >  >> Manufacturing Technology >> 制造工艺

用 Arduino Mega 与 MAX72XX LED 矩阵复刻经典《小行星》游戏

元器件与物料

Arduino Mega 2560×1
MAX7219 LED 矩阵驱动板(MAXREFDES99# 或同类)×1
12 mm 轻触开关×2
有源蜂鸣器×1
面包板 + 跳线×1

项目简介

在 8×8 LED 点阵上复刻 1979 年雅达利街机经典《小行星》:玩家控制飞船(底行单点)左右移动躲避从顶部随机落下的小行星(双点)。游戏随时间加速,碰撞即结束并显示生存分数(滴答数)。两按键分别对应左/右,支持环绕移动。蜂鸣器模拟爆炸音效。代码基于 LedControl 库,结构清晰,适合学习游戏循环、中断去抖、点阵驱动。

接线说明

模块引脚Mega 引脚
DIN (DataIn)12
CLK11
LOAD (CS)10
左键2 (INT0, INPUT_PULLUP)
右键3 (INT1, INPUT_PULLUP)
蜂鸣器9 (PWM)

核心逻辑

完整代码

/*********************************************************
 * Asteroids on MAX72XX LED Matrix
 * (c) 2018 Joshua Weßner
 *********************************************************/
#include "LedControl.h"   // Eberhard Fahle 库

LedControl lc = LedControl(12, 11, 10, 1); // DIN, CLK, LOAD, 1 级联

// 全局变量
unsigned long delaytime = 1000;
int score = 0, tick = 300, tickCounter = 1;
int ship = 3;                 // 飞船列 0-7
int columns[8] = {0};         // 每列小行星行号,0=无
volatile unsigned long btnTime = 0;
const int btnDelay = 150;     // 去抖 ms
volatile bool gameOver = false;
unsigned long now;

void setup() {
  gameOver = false; score = 0; tick = 300; tickCounter = 1; ship = 3;
  now = millis(); btnTime = millis();
  randomSeed(analogRead(A15));
  lc.shutdown(0, false); lc.setIntensity(0, 1); lc.clearDisplay(0);
  pinMode(2, INPUT_PULLUP); pinMode(3, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(2), left, FALLING);
  attachInterrupt(digitalPinToInterrupt(3), right, FALLING);
}

void left() {
  if (millis() - btnTime > btnDelay) {
    ship = (ship == 0) ? 7 : ship - 1;
    lc.clearDisplay(0); btnTime = millis();
  }
  if (gameOver) { gameOver = false; setup(); }
}
void right() {
  if (millis() - btnTime > btnDelay) {
    ship = (ship == 7) ? 0 : ship + 1;
    lc.clearDisplay(0); btnTime = millis();
  }
  if (gameOver) { gameOver = false; setup(); }
}

void loop() {
  if (millis() - now > tick) {
    now = millis(); score++;
    if (tickCounter == 1) {               // 每 4 拍
      tick = tick / 1.02;                 // 加速
      int col = random(0, 8);
      if (columns[col] == 0) columns[col] = 1; // 生成
    }
    tickCounter = (tickCounter == 4) ? 1 : tickCounter + 1;

    // 小行星下落
    for (int i = 0; i < 8; i++) {
      if (columns[i] == 10) columns[i] = 0;
      if (columns[i] != 0) columns[i]++;
    }
    lc.clearDisplay(0);
  }

  // 绘制飞船(底行 row 7)
  lc.setLed(0, 7, ship, true);
  // 绘制小行星(双点)
  for (int i = 0; i < 8; i++) {
    if (columns[i] > 0) {
      lc.setLed(0, columns[i]-2, i, true);
      lc.setLed(0, columns[i]-3, i, true);
    }
  }

  // 碰撞检测
  if (columns[ship] == 9 || columns[ship] == 10) {
    lc.clearDisplay(0);
    // 爆炸动画
    for (int f = 0; f < 4; f++) {
      lc.setLed(0, 7, ship+f, true); lc.setLed(0, 7, ship-f, true);
      lc.setLed(0, 7-f, ship+f, true); lc.setLed(0, 7-f, ship-f, true);
      lc.setLed(0, 7-1.5*f, ship, true);
      unsigned long t = millis(); int rs = 1000;
      while (millis() - t <= 250) { rs--; tone(9, random(rs, 1000)); }
      lc.clearDisplay(0); noTone(9);
    }
    delay(500);

    // 分数显示
    String s = String(score);
    char d0 = s.length()>=3 ? s[0] : '0';
    char d1 = s.length()>=2 ? s[s.length()-2] : s[0];
    char d2 = s[s.length()-1];
    auto drawDigit = [&](char c, int pos) {
      byte pat[3];
      switch(c){
        case '0': pat[0]=B00011111; pat[1]=B00010001; pat[2]=B00011111; break;
        case '1': pat[0]=B00001000; pat[1]=B00011111; pat[2]=0; break;
        case '2': pat[0]=B00010111; pat[1]=B00010101; pat[2]=B00011101; break;
        case '3': pat[0]=B00010001; pat[1]=B00010101; pat[2]=B00011111; break;
        case '4': pat[0]=B00011100; pat[1]=B00000100; pat[2]=B00011111; break;
        case '5': pat[0]=B00011101; pat[1]=B00010101; pat[2]=B00010111; break;
        case '6': pat[0]=B00011111; pat[1]=B00010101; pat[2]=B00010111; break;
        case '7': pat[0]=B00010000; pat[1]=B00010011; pat[2]=B00011100; break;
        case '8': pat[0]=B00011111; pat[1]=B00010101; pat[2]=B00011111; break;
        case '9': pat[0]=B00011101; pat[1]=B00010101; pat[2]=B00011111; break;
        default: pat[0]=pat[1]=pat[2]=0;
      }
      for(int r=0;r<3;r++) if(pat[r]) lc.setColumn(0, pos+r, pat[r]);
    };
    if (score < 100) {
      drawDigit(d1, 1); drawDigit(d2, 5);
    } else {
      drawDigit(d1, 1); drawDigit(d2, 5);
      int hundreds = d0 - '0';
      for (int h = 1; h <= hundreds; h++) {
        lc.setLed(0, 0, h-1, true); lc.setLed(0, 1, h-1, true);
        delay(200);
      }
    }
    gameOver = true;
    while (gameOver) { /* 等待按键 */ }
  }
}

原理图

用 Arduino Mega 与 MAX72XX LED 矩阵复刻经典《小行星》游戏

扩展建议

制造工艺

  1. 国际象棋:从古代起源到现代制造的专家概览
  2. 弹球机:经典街机游戏的历史、设计与制造
  3. 美式橄榄球的演变与工艺:从古老游戏到现代NFL标准
  4. 用 Arduino UNO 和 OLED 显示屏制作经典 Pong 游戏:分步教程
  5. 用 Arduino Nano 自制 37 灯珠轮盘赌游戏机
  6. 用 Arduino Nano 与 MAX7219 制作 24×16 LED Pong 游戏机
  7. 自制 16×8 LED 矩阵俄罗斯方块游戏机:Arduino Nano + 74HC595 驱动
  8. Arduino + 模拟摇杆互动游戏:五向 LED 反馈
  9. 互动 LED 矩阵门显:PIR 触发节日问候 + 待机特效
  10. 声控 8 路 LED 灯光秀:Arduino 入门项目
  11. 从零构建智能 Arduino 四足机器人:完整指南
  12. DIY 热熔胶棒 LED 矩阵灯 — 打造多彩显示屏