驴友花雕 发表于 2025-6-19 18:35:46

【Arduino 动手做】 基于街机游戏《Cyclone》的LED环

基于街机游戏《Cyclone》,玩家需要尝试在特定位置停止 LED 的圆圈滚动。

这次我将向你展示如何制作一款有趣的游戏,它基于一款名为“Cyclone”的街机游戏。游戏中,玩家需要尝试在特定位置停止 LED 灯的循环滚动。游戏的目标是在 LED 灯到达指示点(红色)时停止循环滚动。如果成功,难度级别将会增加。如果失败,游戏将重新开始。

圆环由 60 个 LED 灯组成(4 个四分之一圆 Neopixel 灯,每个灯由 15 个 LED 组成)。圆环支架由 3D 打印机制作,您可以下载下方的 .stl 文件。圆环中间是一条由 6 个 RGB LED 组成的灯带,代表六个等级。基本代码取自 oKeeg 的 Instructable,我做了一些修改,使游戏更加有趣。

首先,我降低了二极管的光强度,因为在我的游戏版本中 LED 是直接可见的。
然后,环中包含 60 个 LED,而不是 40 个,因为我从我之前的一个项目(LED 环形时钟)中使用了它。
我还添加了两个级别,这样游戏现在总共有 6 个级别。
下一个非常重要的修改是我在游戏中添加了声音,现在玩起来更有趣了。
-最后,我制作了一个大的街机按钮,以便更准确地玩游戏。

游戏需要 5V/3A 或更高的电源供电。这是一个非常简单的项目,仅包含几个组件:

- Arduino 纳米微控制器

- WS2812 LED 环,带 60 个 RGB LED

- WS2812 LED 灯带,带 6 个 RGB LED

- 一个晶体管

- 蜂鸣器

- 以及大型 DIY 街机按钮

您在图片中看到的实时时钟模块未处于活动状态,并且是我之前项目的一部分。

我们也可以使用上一个项目剩下的旋转编码器按钮。在这种情况下,设备小巧紧凑,但操作起来比较困难。

启动游戏时,所有 LED 都会亮起不同的颜色。按下按钮,游戏开始。目标是在旋转二极管恰好​​位于静态二极管上时按下按钮。在前两级中,三个二极管是静态的,在接下来的级别中只有一个。而且,随着每个级别的增加,二极管的速度都会增加,因此在所需的时刻按下按钮会变得越来越困难。每完成一个级别,水平行中的一个二极管就会亮起。总共有六个级别,所以这一行包含六个二极管。如果我们未能通过该级别,游戏将从头开始。如果您通过了所有六个级别,游戏也将从头开始。

最后,将该装置装入由PVC板制成并涂有自粘彩色壁纸的合适盒子中。











驴友花雕 发表于 2025-6-19 18:38:14

【Arduino 动手做】 基于街机游戏《Cyclone》的LED环

项目代码

#include "FastLED.h"
#define NUM_LEDS 60
#define DATA_PIN A0
#define SCORE_PIN 6
#define SCORE_LEDS 6
#define BRIGHTNESS 55
CRGB leds;
CRGB sleds;

bool reachedEnd = false;
byte gameState = 0;
//byte ledSpeed = 0;
int period = 1000;
unsigned long time_now = 0;
byte Position = 0;
byte level = 0;

const byte ledSpeed = {50, 40, 30, 20, 14, 7};

//Debounce
bool findRandom = false;
byte spot = 0;

void setup() {
// put your setup code here, to run once:
FastLED.addLeds<WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS);
FastLED.addLeds<WS2812B, SCORE_PIN, GRB>(sleds, SCORE_LEDS);
pinMode(A3, INPUT_PULLUP);
Serial.begin(9600);
Serial.println("Reset");
}

void loop() {
// put your main code here, to run repeatedly:
FastLED.setBrightness(BRIGHTNESS );
if (gameState == 0) {
    fill_rainbow(leds, NUM_LEDS, 0, 20); //2 = longer gradient strip
    fill_rainbow(sleds, SCORE_LEDS, 0, 40); //2 = longer gradient strip

    if (digitalRead(A3) == LOW) {
      Position = 0;
      findRandom = true;
      delay(500);
      for (byte i = 0; i < NUM_LEDS; i++) {
      leds.setRGB(0, 0, 0);
      delay(40);
      FastLED.show();
       int thisPitch = map (i, 60, 0, 100, 1500);
       tone(9, thisPitch,120);
      }
      for (byte i = 0; i < SCORE_LEDS; i++) {
      sleds.setRGB(0, 0, 0);
      delay(100);
      FastLED.show();
      }
      gameState = 1;
    }
    FastLED.show();
}
if (gameState == 1) {
    period = ledSpeed;
    if (millis() > time_now + period) {
      time_now = millis();
      if (findRandom) {
      spot = random(56) + 3;
      findRandom = false;
      }
      leds.setRGB(255, 140, 0);
      leds.setRGB(0, 255, 0);
      leds.setRGB(255, 110, 0);
      sleds.setRGB(0, 255, 0);
      PlayGame(spot - 1, spot + 1);
    }
    if (digitalRead(A3) == LOW) {
      delay(300);
      findRandom = false;
      if (Position > spot - 1 && Position < spot + 3) {
      level = gameState;
      gameState = 98;
      } else {
      gameState = 99;
      }
    }
}
if (gameState == 2) {
//    period = 320;
    period = ledSpeed;
    if (millis() > time_now + period) {
      time_now = millis();
      if (findRandom) {
      spot = random(56) + 3;
      findRandom = false;
      }
      leds.setRGB(255, 190, 0);
      leds.setRGB(0, 255, 0);
      leds.setRGB(255, 190, 0);
      sleds.setRGB(255, 255, 0);
      PlayGame(spot - 1, spot + 1);
    }
    if (digitalRead(A3) == LOW) {
      delay(300);
      if (spot - 1 && Position < spot + 3) {
      level = gameState;
      gameState = 98;
      } else {
      gameState = 99;
      }
    }
}
if (gameState == 3) {
    period = ledSpeed;
    if (millis() > time_now + period) {
      time_now = millis();
      if (findRandom) {
      spot = random(56) + 3;
      findRandom = false;
      }
      leds.setRGB(0, 255, 0);
      sleds.setRGB(255, 50, 0);
      PlayGame(spot, spot);
    }
    if (digitalRead(A3) == LOW) {
      delay(300);
      if (Position == spot+1) {
      level = gameState;
      gameState = 98;
      } else {
      gameState = 99;
      }
    }
}
if (gameState == 4) {
    period = ledSpeed;
    if (millis() > time_now + period) {
      time_now = millis();
      if (findRandom) {
      spot = random(56) + 3;
      findRandom = false;
      }
      leds.setRGB(0, 255, 0);
      sleds.setRGB(255, 0, 0);
      PlayGame(spot, spot);
    }
    if (digitalRead(A3) == LOW) {
      delay(300);
      if (Position == spot+1) {
      level = gameState;
      gameState = 98;
      } else {
      gameState = 99;
      }
    }
}

if (gameState == 5) {
    period = ledSpeed;
    if (millis() > time_now + period) {
      time_now = millis();
      if (findRandom) {
      spot = random(56) + 3;
      findRandom = false;
      }
      leds.setRGB(0, 255, 0);
      sleds.setRGB(0, 50, 255);
      PlayGame(spot , spot);
    }
    if (digitalRead(A3) == LOW) {
      delay(300);
      if (Position == spot+1) {
      level = gameState;
      gameState = 98;
      } else {
      gameState = 99;
      }
    }
}

if (gameState == 6) {
    period = ledSpeed;
    if (millis() > time_now + period) {
      time_now = millis();
      if (findRandom) {
      spot = random(56) + 3;
      findRandom = false;
      }
      leds.setRGB(0, 255, 0);
      sleds.setRGB(0, 150, 255);
      PlayGame(spot , spot);
    }
    if (digitalRead(A3) == LOW) {
      delay(300);
      if (Position == spot+1) {
      level = gameState;
      gameState = 98;
      } else {
      gameState = 99;
      }
    }
}

if (gameState == 98) {
    winner();
}
if (gameState == 99) {
    loser();
}
}
void PlayGame(byte bound1, byte bound2) {
leds.setRGB(255, 0, 0);
if (Position < bound1 + 1 || Position > bound2 + 1) {
    leds.setRGB(0, 0, 0);
}
FastLED.show();
Position++;
if (Position >= NUM_LEDS) {
    leds.setRGB(0, 0, 0);
    Position = 0;
}
}

void winner() {
for (byte i = 0; i < 3; i++) {
    for (byte j = 0; j < NUM_LEDS; j++) {
      leds.setRGB(0, 255, 0);
      tone(9, 1000, 250);
    }
    FastLED.show();
    delay(500);
    clearLEDS();
    FastLED.show();
    delay(500);

}
findRandom = true;
Position = 0;

gameState = level + 1;
if (gameState > 6) {
    gameState = 0;
}
}
void loser() {
for (byte i = 0; i < 3; i++) {
    for (byte j = 0; j < NUM_LEDS; j++) {
      leds.setRGB(255, 0, 0);
      tone(9, 200, 250);
    }
    FastLED.show();
    delay(500);
    clearLEDS();
    FastLED.show();
    delay(500);
}
gameState = 0;
}
void clearLEDS() {
for (byte i = 0; i < NUM_LEDS; i++) {
    leds.setRGB(0, 0, 0);
}
}
void winAll(){

}


驴友花雕 发表于 2025-6-19 18:40:05

【Arduino 动手做】 基于街机游戏《Cyclone》的LED环

【Arduino 动手做】 基于街机游戏《Cyclone》的LED环
项目链接:https://www.hackster.io/mircemk/ ... 12b-led-ring-738c58
项目作者:北马其顿 米尔塞姆克(Mirko Pavleski)

项目视频 :https://www.youtube.com/watch?v=1K0vr-hrh0k
项目代码:https://www.hackster.io/code_files/581838/download
3D 文件:https://hacksterio.s3.amazonaws. ... ring_Vvyxo74B6t.stl





页: [1]
查看完整版本: 【Arduino 动手做】 基于街机游戏《Cyclone》的LED环