/* 參考 https://blog.jmaker.com.tw/arduino-buttons/ 上拉電阻
改用上拉電阻為按鈕,取LOW為按下的訊號(Pin腳如果是在空接時用digitalRead()讀,
會有雜訊的影響,在Floating狀態。)第7腳為內建上拉電阻。
GameState=0
開始亂數燈>>按下鈕>led_run_at=0 且 Go_Play=true -->GameState=1
>GameState=1
延時週期period(設)> if 週期過了> 擷取當下時間放入Time_Get > 亂數值放入=Set_Led >改Go_Play=false
亮Set_Led > 開始跑馬燈(函式)> 亮該燈其於忽略 >累加 >if 超過總燈數,歸零
*/
//由範例中取得循環(加入"關閉之後的燈",i-1)
#include <Adafruit_NeoPixel.h>
#define LED_PIN 2 // LED環號,訊號腳位.
#define KEY_PUSH 7 //按鈕控制腳位
#define NUMLEDS 16 //環燈顆數
#define BRIGHTNESS 130 //LED燈亮度在15~50即可,最大亮度為255
Adafruit_NeoPixel RingLED(NUMLEDS, LED_PIN, NEO_GRB + NEO_KHZ800);
#define DELAYVAL 100 // 延遲時間
int period = 1000; //計時的時間
int GameState = 0; //遊戲初始狀態=0 1(第1關-3燈) 2(第2關-2燈) 3(第3關-1燈)
byte Score=0;
byte Speed=0;
byte Set_Led[]={0, 0, 0};//用陣列設定號燈(3燈=3個陣列.2燈2個陣列.1燈1個陣列)
//byte RingSpeed[] = {100, 70, 50, 30}; //共有4個等級的遊戲
byte RingSpeed[] = {100, 100, 100, 100}; //共有4個等級的遊戲
byte led_run_at = 0; //跑馬燈號現在位置
byte LEVEL=0;//累計關卡用
int Setting_Led = 0; //遊戲設定點(亂數值存放)
boolean Go_Play = false;//遊戲處於等待狀態
unsigned long Time_Get = 0;//擷取時間點
//-----環燈初始化動作
void setup() {
RingLED.begin(); //初始化(環燈)
RingLED.setBrightness(BRIGHTNESS); //環燈亮度
Time_Get = millis();//擷取開機時間
pinMode(KEY_PUSH, INPUT_PULLUP);//按鈕輸入腳7(KEY_PUSH)
Serial.begin(115200);//串列傳輸啟動
randomSeed(analogRead(KEY_PUSH));//--解決亂數不亂的問題(擷取亂數因子)
}
//------無窮迴圈------
void loop() {
if (GameState == 0){
if (digitalRead(KEY_PUSH) == LOW && Go_Play == false) { //按鈕被按下去,往下做
delay(180);//會影響循環燈
led_run_at = 0;//循環紅點位置
Go_Play = true;//被按下去LOW,變數為true,開始要玩遊戲
Serial.print("!");//判斷按鈕準不準
GameState=1;
Level_1();//往第1關開始遊戲~第3關結束(每關4種速度)
}
}
}
//-----第1關(3顆設定燈):------
void Level_1(){
RingLED.clear();//清除燈號
led_run_at=0;//跑馬燈歸零
while (GameState == 1) {
period = RingSpeed[Speed]; //(陣列中的數字愈大愈慢)
//=====取亂數置入設定點-->再延伸成3個設定燈=====
if (millis()-Time_Get > period){ // (亮燈週期過了,再重設週期)
Time_Get = millis(); // 擷取當下時間放入Time_Get
//====亂數設定OK了嗎? Yes(改false)
if(Go_Play==true){ //首次-->設號燈
Setting_Led = random(NUMLEDS);
Go_Play = false; //隨機設定號燈完畢,回歸,等待按鈕!
}
//-------------------------------------------
//====以下亮3個號燈====
Set_Led[0]=Setting_Led; //陣列0=放入亂數值
if(Setting_Led == 14){
Set_Led[1]=15;
Set_Led[2]=0;}
else if(Setting_Led == 15){
Set_Led[1]=0;
Set_Led[2]=1;}
else{
Set_Led[1]=Set_Led[0]+1;
Set_Led[2]=Set_Led[0]+2;}
RingLED.setPixelColor(Set_Led[0], 0, 255, 0);//(綠)
RingLED.setPixelColor(Set_Led[1], 0, 255, 0);//(綠)
RingLED.setPixelColor(Set_Led[2], 0, 255, 0);//(綠)
RingLED.show();
LED_Runing();//呼叫跑馬燈
Check_Push();//檢查闖關者,按鈕是否被按下
//Serial.println(GameState);//查看勝利或失敗
}
}
}
//----跑馬燈----
void LED_Runing(){
led_run_at++; //循環燈...往下累加
if (led_run_at >= NUMLEDS) { //如果循環紅點位置=60符合則歸零
RingLED.setPixelColor(led_run_at-1, 0, 0, 0);//最後一顆歸0
led_run_at = 0;//歸零
}
RingLED.setPixelColor(led_run_at, 255, 0, 0);//亮燈
RingLED.setPixelColor(led_run_at-1, 0, 0, 0);//往後關燈
RingLED.show();
}
void Check_Push(){ //Go_Play == false為等待的意思
if (digitalRead(KEY_PUSH) == LOW && Go_Play == false ) { //按鈕被按下去,往下做
delay(180);
Go_Play=true;
Serial.print("S");//判斷按鈕準不準
//----得分-------
if (Set_Led[0]==led_run_at || Set_Led[1]==led_run_at || Set_Led[2]==led_run_at) {
// GameState = 100; //勝利
Score++;
ScreLed(Score);//呼叫計分燈號函式
// GameState = 1;
}
//----遺漏(不計分)----
else{
// GameState =99;
ScreLed(Score);
// GameState = 1;
}
Speed++; //換下個速度檔次
Serial.print(Speed);//查看勝利或失敗 */
Serial.print(">");
//若4種檔次完成,換第二關
if(Speed==4){
GameState =2;
Speed=0;}
}
}
//----計分燈號----
void ScreLed(byte Gain){
RingLED.clear();//清除燈號
for(byte i=0;i<Gain;i++){RingLED.setPixelColor(i, 255 , 255, 0);}
RingLED.show();
delay(1400);
RingLED.clear();//清除燈號
}