回到首页 返回首页
回到顶部 回到顶部
返回上一页 返回上一页

【Arduino 动手做】DIY Arduino Cyclone 游戏,带 WS2812B LED 环 简单

头像 驴友花雕 2025.06.19 22 2

基于街机游戏《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板制成并涂有自粘彩色壁纸的合适盒子中。

 

01.jpg
02.jpg
03.jpg
04.jpg
schematic_supU5hezie.jpg

项目代码

 

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

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[6] = {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[i].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[i].setRGB(0, 0, 0);
        delay(100);
        FastLED.show();
      }
      gameState = 1;
    }
    FastLED.show();
  }
  if (gameState == 1) {
    period = ledSpeed[0];
    if (millis() > time_now + period) {
      time_now = millis();
      if (findRandom) {
        spot = random(56) + 3;
        findRandom = false;
      }
      leds[spot - 1].setRGB(255, 140, 0);
      leds[spot].setRGB(0, 255, 0);
      leds[spot + 1].setRGB(255, 110, 0);
      sleds[0].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[1];
    if (millis() > time_now + period) {
      time_now = millis();
      if (findRandom) {
        spot = random(56) + 3;
        findRandom = false;
      }
      leds[spot - 1].setRGB(255, 190, 0);
      leds[spot].setRGB(0, 255, 0);
      leds[spot + 1].setRGB(255, 190, 0);
      sleds[1].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[2];
    if (millis() > time_now + period) {
      time_now = millis();
      if (findRandom) {
        spot = random(56) + 3;
        findRandom = false;
      }
      leds[spot].setRGB(0, 255, 0);
      sleds[2].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[3];
    if (millis() > time_now + period) {
      time_now = millis();
      if (findRandom) {
        spot = random(56) + 3;
        findRandom = false;
      }
      leds[spot].setRGB(0, 255, 0);
      sleds[3].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[4];
    if (millis() > time_now + period) {
      time_now = millis();
      if (findRandom) {
        spot = random(56) + 3;
        findRandom = false;
      }
      leds[spot].setRGB(0, 255, 0);
      sleds[4].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[5];
    if (millis() > time_now + period) {
      time_now = millis();
      if (findRandom) {
        spot = random(56) + 3;
        findRandom = false;
      }
      leds[spot].setRGB(0, 255, 0);
      sleds[5].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[Position].setRGB(255, 0, 0);
  if (Position < bound1 + 1 || Position > bound2 + 1) {
    leds[Position - 1].setRGB(0, 0, 0);
  }
  FastLED.show();
  Position++;
  if (Position >= NUM_LEDS) {
    leds[Position - 1].setRGB(0, 0, 0);
    Position = 0;
  }
}

void winner() {
  for (byte i = 0; i < 3; i++) {
    for (byte j = 0; j < NUM_LEDS; j++) {
      leds[j].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[j].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[i].setRGB(0, 0, 0);
  }
}
void winAll(){
  
}

【Arduino 动手做】 基于街机游戏《Cyclone》的LED环
项目链接:https://www.hackster.io/mircemk/diy-arduino-cyclone-game-with-ws2812b-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.com/uploads/attachments/1422211/ring_Vvyxo74B6t.stl
 

00.jpg
00165--.gif

评论

user-avatar
  • 寸进

    寸进2025.06.21

    真的很酷炫啊

    1
    • 驴友花雕

      驴友花雕2025.06.21

      谢谢鼓励啊

icon 他的勋章
    展开更多