/*
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// # # # # # ###### ####### ####### # #######
// ## ## # # ## # # # # # # # # #
// # # # # # # # # # # # # # # # # #
// # # # # # # # # # # # # # # # #####
// # # ####### # # # # # # # # ####### #
// # # # # # ## # # # # # # # #
// # # # # # # ###### ####### ####### # # #
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
// Stacker Game Code
#include <MD_MAX72xx.h>
#include <MD_Parola.h>
#include <Adafruit_NeoPixel.h>
#define PIN_LED 9
#define TOTAL_LED 8
Adafruit_NeoPixel strip = Adafruit_NeoPixel(TOTAL_LED, PIN_LED, NEO_GRB + NEO_KHZ800);
int index_led = 0;
unsigned long waktu_led = 0;
#define MATRIX_WIDTH 8
#define MATRIX_HEIGHT 32
// #include "MZF_Font.h"
MD_MAX72XX::fontType_t MZFStackerFont[] PROGMEM = {
'F', 1, 32, 127, 5,
2, 0, 0, // 32 - 'Space'
6, 24, 24, 36, 102, 102, 66, // 2 - '!'
3, 3, 0, 3, // 34 - '"'
6, 102, 102, 102, 102, 102, 102, // 35 - '#'
6, 126, 126, 0, 0, 126, 126, // 36 - '$'
8, 129, 129, 129, 129, 129, 129, 129, 129, // 37 - '%'
8, 129, 129, 0, 129, 129, 0, 129, 129, // 38 - '&'
1, 3, // 39
2, 60, 66, // 40 - '('
2, 66, 60, // 41 - ')'
3, 10, 4, 10, // 42 - '*'
6, 24, 24, 126, 126, 24, 24, // 43 - '+'
2, 16, 8, // 44 - ','
6, 0, 0, 126, 126, 0, 0, // 45 - '-'
1, 16, // 46 - '.'
3, 8, 4, 2, // 47 - '/'
5, 24, 36, 36, 36, 24, // 17 - '0'
5, 8, 24, 8, 8, 8, // 18 - '1'
5, 60, 4, 60, 32, 60, // 19 - '2'
5, 60, 4, 28, 4, 60, // 20 - '3'
5, 36, 36, 60, 4, 4, // 21 - '4'
5, 60, 32, 60, 4, 60, // 22 - '5'
5, 60, 32, 60, 36, 60, // 23 - '6'
5, 60, 4, 4, 4, 4, // 24 - '7'
5, 60, 36, 60, 36, 60, // 25 - '8'
5, 60, 36, 60, 4, 60, // 26 - '9'
1, 10, // 58 - ':'
2, 16, 10, // 59 - ';'
3, 4, 10, 17, // 60 - '<'
5, 126, 126, 0, 126, 126, // 61 - '='
3, 17, 10, 4, // 62 - '>'
3, 1, 21, 3, // 63 - '?'
6, 66, 102, 102, 36, 24, 24, // 33 - '@'
8, 60, 126, 102, 126, 126, 102, 102, 102, // 34 - 'A'
8, 124, 126, 102, 124, 124, 102, 126, 124, // 35 - 'B'
8, 62, 126, 96, 96, 96, 96, 126, 62, // 36 - 'C'
8, 124, 126, 102, 102, 102, 102, 126, 124, // 37 - 'D'
8, 126, 126, 96, 120, 120, 96, 126, 126, // 38 - 'E'
8, 126, 126, 96, 120, 120, 96, 96, 96, // 39 - 'F'
8, 62, 126, 96, 96, 110, 98, 126, 62, // 40 - 'G'
8, 102, 102, 102, 126, 126, 102, 102, 102, // 41 - 'H'
8, 24, 24, 24, 24, 24, 24, 24, 24, // 42 - 'I'
8, 12, 12, 12, 12, 12, 12, 60, 56, // 43 - 'J'
8, 102, 110, 108, 120, 120, 108, 110, 102, // 44 - 'K'
8, 96, 96, 96, 96, 96, 96, 126, 126, // 45 - 'L'
8, 102, 126, 126, 102, 102, 102, 102, 102, // 46 - 'M'
8, 102, 118, 126, 110, 102, 102, 102, 102, // 47 - 'N'
8, 60, 126, 102, 102, 102, 102, 126, 60, // 48 - 'O'
8, 124, 126, 102, 126, 124, 96, 96, 96, // 49 - 'P'
8, 60, 126, 102, 102, 102, 126, 60, 12, // 50 - 'Q'
8, 124, 126, 102, 124, 124, 102, 102, 102, // 51 - 'R'
8, 126, 126, 96, 124, 62, 6, 126, 126, // 52 - 'S'
8, 126, 126, 24, 24, 24, 24, 24, 24, // 53 - 'T'
8, 102, 102, 102, 102, 102, 102, 126, 60, // 54 - 'U'
8, 102, 102, 102, 102, 102, 102, 60, 24, // 55 - 'V'
8, 102, 102, 102, 102, 102, 126, 126, 102, // 56 - 'W'
8, 66, 102, 102, 60, 60, 102, 102, 66, // 57 - 'X'
8, 102, 102, 102, 60, 24, 24, 24, 24, // 58 - 'Y'
8, 126, 126, 14, 28, 56, 112, 126, 126, // 59 - 'Z'
2, 31, 17, // 91 - '['
3, 2, 4, 8, // 92 - '\'
2, 17, 31, // 93 - ']'
3, 2, 1, 2, // 94 - '^'
3, 16, 16, 16, // 95 - '_'
2, 1, 2, // 96 - '`'
5, 60, 36, 60, 36, 36, // 66 - 'a'
5, 56, 36, 60, 36, 56, // 67 - 'b'
5, 28, 32, 32, 32, 28, // 68 - 'c'
5, 56, 36, 36, 36, 56, // 69 - 'd'
5, 60, 32, 56, 32, 60, // 70 - 'e'
5, 60, 32, 56, 32, 32, // 71 - 'f'
5, 60, 32, 44, 36, 60, // 72 - 'g'
5, 36, 36, 60, 36, 36, // 73 - 'h'
5, 24, 24, 24, 24, 24, // 74 - 'i'
5, 4, 4, 4, 36, 28, // 75 - 'j'
5, 36, 40, 48, 40, 36, // 76 - 'k'
5, 32, 32, 32, 32, 60, // 77 - 'l'
5, 126, 90, 90, 82, 66, // 78 - 'm'
5, 36, 52, 44, 36, 36, // 79 - 'n'
5, 60, 36, 36, 36, 60, // 80 - 'o'
5, 56, 36, 56, 32, 32, // 81 - 'p'
5, 60, 36, 36, 60, 8, // 82 - 'q'
5, 60, 36, 60, 40, 36, // 83 - 'r'
5, 60, 32, 60, 4, 60, // 84 - 's'
5, 60, 24, 24, 24, 24, // 85 - 't'
5, 36, 36, 36, 36, 60, // 86 - 'u'
5, 36, 36, 36, 60, 24, // 87 - 'v'
5, 66, 90, 90, 126, 126, // 88 - 'w'
5, 36, 36, 24, 36, 36, // 89 - 'x'
5, 36, 36, 24, 8, 16, // 90 - 'y'
5, 60, 4, 8, 16, 60, // 91 - 'z'
3, 4, 27, 17, // 123 - '{'
1, 27, // 124 - '|'
3, 17, 27, 4, // 125 - '}'
3, 6, 2, 3, // 126 - '~'
3, 31, 31, 31, // 127 - 'Full Block'
};
// Konfigurasi jumlah perangkat di rangkaian dan antarmuka hardware
#define HARDWARE_TYPE MD_MAX72XX::PAROLA_HW
// #define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define MAX_DEVICES 4
#define CLK_PIN 13 // atau SCK
#define DATA_PIN 11 // atau MOSI
#define CS_PIN 10 // atau SS
// Inisialisasi matriks LED
MD_MAX72XX mx = MD_MAX72XX(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
MD_Parola P = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
#define BUTTON_PIN 12
bool clicked = false;
bool push = false;
bool game = 0;
uint8_t anim = 2;
uint8_t win = 32;
bool cur = 0;
bool goingLeft = true; // Bergerak ke kiri jika true, ke kanan jika false.
const int buzzerPin = 6; // Jika ada buzzer, atur ke -1 untuk menonaktifkan.
const int top = MATRIX_HEIGHT; // Tinggi strip, dapat disesuaikan jika menggunakan matriks lebih besar
const int bottom = 0; // Kurangi satu dari atas jika menggunakan seluruh strip.
const int maxHeight = MATRIX_HEIGHT;
unsigned long buttonwait = 0;
unsigned long prevMillis = 0; // Waktu sebelumnya dalam milidetik
unsigned long curMillis = 0; // Waktu saat ini dalam milidetik, untuk mencegah panggilan ganda ke millis()
const long animationDuration = 2000; // Durasi animasi saat kehilangan blok
long defaultInterval = 300; // Waktu mulai antara pembaruan
int intervalModifier = 25; // pengurangan waktu atau delay kecepatan
long maxSpeed = 50; // Kecepatan maksimum yang diizinkan untuk blok. Jangan atur ke negatif
long interval = defaultInterval; // Waktu antara pembaruan. Ini tidak boleh dibuat sebagai const, karena akan berubah.
int cursize = 3; // Ukuran blok yang ditumpuk
int curpos = 3; // Posisi blok
int prevcurpos = 0; // Posisi blok
int currow = bottom; // Baris LED tempat blok berada
// State variable using integers
int currentState = 0; // 0 for STROBE, 1 for SCROLL
int step = 0;
// Timing variables
unsigned long previousMillis = 0;
const long strobeInterval = 300; // Time between strobe flashes
const long scrollInterval = 100; // Time between scroll updates
unsigned long strobeTiming = 0; // To control strobe effect timing
bool isCharacterVisible = false; // Track visibility of the character
unsigned long waktu = 0;
unsigned long lastButtonPressTime = 0;
unsigned long waktustandby = 10;
byte jeda = 0;
void setup()
{
Serial.begin(9600);
Serial.println("STACKER MATRIX MAX 7219");
strip.begin();
strip.setBrightness(255);
mx.begin();
mx.control(MD_MAX72XX::INTENSITY, 1);
P.begin();
P.setIntensity(1);
P.setFont(MZFStackerFont);
P.setTextAlignment(PA_CENTER);
mx.clear();
if (maxSpeed < 0) {
maxSpeed = 0;
Serial.println("Error: Kecepatan maksimum diatur ke negatif.");
}
pinMode(BUTTON_PIN, INPUT_PULLUP);
int value = digitalRead(BUTTON_PIN);
}
int lastState = HIGH;
int value = HIGH;
bool checkAir(); // Memeriksa apakah blok berada di udara atau di atas blok lain
void drawBlock(); // Panggilan untuk menggambar
void onUpdate(); // Panggilan untuk pembaruan
void resetGame(); // Fungsi untuk mereset permainan
void failState(int echo); // Dipanggil saat pemain kalah
void winState(); // Dipanggil saat pemain menang
void animatedrop(int pos, int width); // Animasi jatuh
void animatedrop(int pos, int width, bool isFail); // Animasi jatuh jika pemain kalah
void buttonPressed(); // Dipanggil saat tombol ditekan.
// display text
bool scrl = 0;
uint8_t scrollDirection = PA_SCROLL_LEFT;
int index = 0;
uint32_t Wheel(byte WheelPos) {
WheelPos = 255 - WheelPos;
if (WheelPos < 85) {
return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
}
if (WheelPos < 170) {
WheelPos -= 85;
return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
}
WheelPos -= 170;
return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}
void pingpong(const char* curMessage, int d) {
P.displayClear();
P.displayScroll(curMessage, PA_CENTER, scrollDirection, d);
P.displayReset(); // Initialize the display with the current scroll direction
}
void v_pingpong(const char* curMessage, int d) {
if (P.displayAnimate()) {
// Ubah arah berdasarkan nilai scrollDirection saat ini
if (scrl == 0) {
scrollDirection = PA_SCROLL_LEFT;
scrl = 1;
} else {
scrollDirection = PA_SCROLL_RIGHT;
scrl = 0;
}
pingpong(curMessage, d); // Restart scrolling dengan arah baru
}
}
void v_1huruf(const char* curMessage, int d) {
// Check if enough time has passed to print the next character
if (millis() - waktu >= d) {
waktu = millis(); // Update the last action time
if (index < strlen(curMessage)) {
P.print(curMessage[index]); // Print the current character
strip.setBrightness(255);
index++; // Move to the next character
} else {
P.print(""); // Clear display after the message is printed
strip.setBrightness(0);
index = 0; // Reset the index to restart
waktu += 1000; // Add an additional delay after printing all characters
}
}
}
void onUpdate() {
if (goingLeft) { // Jika bergerak ke kiri
if (curpos > 0) { // Periksa jika bisa bergerak ke kiri
curpos--; // Jika bisa, mari kita pergi ke kiri
} else { // Jika tidak...
curpos++; // Mari kita pergi ke kanan
goingLeft = false; // Dan pastikan kita benar-benar bergerak ke kanan.
}
} else { // Jika bergerak ke kanan
if (curpos + cursize < MATRIX_WIDTH) { // Periksa jika bisa bergerak ke kanan
curpos++; // Jika bisa, mari kita pergi ke kanan.
} else { // Jika tidak...
curpos--; // Pergi ke kiri
goingLeft = true; // Dan benar-benar pergi ke kiri
}
}
drawBlock(); // Akhirnya kita bisa menggambar
prevMillis = curMillis;
}
void drawBlock() {
// Serial.println(curpos);
int r = curpos;
int c = currow;
mx.setPoint(r, c, true);
mx.setPoint(r, c + 1, true);
if (cursize > 1) { // Periksa jika ada lebih dari satu
if (cursize == 3) { // Jika ada tiga, kita bisa menggambar yang ketiga
int r = curpos + 2;
int c = currow;
mx.setPoint(r, c, true);
mx.setPoint(r, c + 1, true);
}
int r = curpos + 1;
int c = currow;
mx.setPoint(r, c, true);
mx.setPoint(r, c + 1, true);
}
if (goingLeft) { // Jika pergerakan ke kiri
int r = curpos + cursize;
int c = currow;
mx.setPoint(r, c, false);
mx.setPoint(r, c + 1, false);
} else {
int r = curpos - 1;
int c = currow;
mx.setPoint(r, c, false);
mx.setPoint(r, c + 1, false);
}
}
bool checkAir() {
Serial.println("Check");
waktustandby = 60;
if (cursize == 3) { // Jika 3 lebar
if (curpos + 2 == prevcurpos + 2) {
return false;
} else if (curpos + 1 == prevcurpos + 2) {
cursize -- ; // 1 blok telah jatuh
animatedrop(curpos + 2, 1);
return false;
} else if (curpos == prevcurpos + 2) {
cursize -= 2 ; // 2 blok telah jatuh
animatedrop(curpos + 1, 2);
return false;
} else if (curpos + 2 == prevcurpos + 1) {
cursize -- ; // 1 blok telah jatuh
animatedrop(curpos, 1);
curpos = curpos + 1;
return false;
} else if (curpos + 2 == prevcurpos) {
cursize -= 2 ; // 2 blok telah jatuh
animatedrop(curpos, 2);
curpos = curpos + 2;
return false;
} else {
failState(3); // Kondisi gagal, blok tunggal jatuh
return true;
}
} else if (cursize == 2) {
if (curpos + 1 == prevcurpos + 1) {
return false;
} else if (curpos == prevcurpos + 1) {
if (cur == 0) {
cursize -- ; // 1 blok telah jatuh
animatedrop(curpos + 1, 1);
}
return false;
} else if (curpos == prevcurpos + 2 && cur == 1) {
cursize -- ; // 1 blok telah jatuh
animatedrop(curpos + 1, 1);
return false;
}
else if (curpos + 1 == prevcurpos) {
cursize -- ; // 1 blok telah jatuh
animatedrop(curpos, 1);
curpos = curpos + 1;
return false;
} else {
failState(2); // Kondisi gagal, blok tunggal jatuh
return true;
}
} else {
if (curpos == prevcurpos) {
return false;
}
else if (curpos == prevcurpos + 1 && cur == 1) {
return false;
} else {
failState(1); // Kondisi gagal, blok tunggal jatuh
return true;
}
}
cur = 0;
}
void resetGame() {
waktustandby = 10;
Serial.println("ResetGame");
cur = 0;
curpos = 2;
currow = bottom;
cursize = 3;
defaultInterval = random(6, 11) * 50;
// Serial.print("defaultInterval =>"); Serial.println(defaultInterval);
interval = defaultInterval;
mx.clear();
push = 0;
curMillis = millis();
prevMillis = curMillis; // Waktu sebelumnya dalam milidetik
}
void winState() {
push = 1;
Serial.println("WIN"); // Mengeluarkan sukses
for (int i = 0; i < 5; i++) {
P.print("win");
delay(500);
mx.clear();
delay(200);
}
if (buzzerPin != -1) { // Mainkan sedikit lagu jika bisa
tone(buzzerPin, 1000, 100);
delay(100);
tone(buzzerPin, 1200, 100);
delay(100);
tone(buzzerPin, 1000, 100);
}
currentState = 4;
}
void failState(int echo) { // Fungsi untuk akhir permainan
push = 1;
// Serial.print("\nFailstate! ");
// Serial.print(echo);
// Serial.print("\n");
// Animasi kegagalan
animatedrop(curpos, cursize, true);
doFall(currow);
for (int i = 0; i < 3; i++) {
P.print("loser");
for (uint8_t i = 0; i < strip.numPixels(); i++) {
strip.setPixelColor(i, strip.Color(255, 0, 0));
strip.show();
}
delay(500);
mx.clear();
ledclear();
delay(200);
}
jeda = 1;
resetGame(); // Reset permainan untuk bermain lagi
}
void doFall(int rows) {
for (int j = 0; j <= 7; j++) { // Iterate through columns
for (int i = 0; i <= rows; i++) {
if (mx.getPoint(7 - j, rows - i)) { // Check if the point is on
mx.setPoint(7 - j, rows - i - 2, false); // Turn off the point two rows down
mx.setPoint(7 - j, rows - i - 1, true); // Turn on the point one row down
mx.setPoint(7 - j, rows - i, false); // Turn off the current point
// Generate a random delay between 20 and 100 milliseconds, in increments of 20
int delayTime = 10 * (random(1, 6)); // random(1, 6) generates 1 to 5, resulting in delays of 20, 40, 60, 80, or 100
delay(delayTime); // Delay for the generated time
}
}
}
}
void animatedrop(int pos, int width) { // Fungsi ini menganimasi kehilangan blok saat pemain melewati batas
Serial.println("- - -");
unsigned long tillAnimation = curMillis + animationDuration;
unsigned long blinkTimer = curMillis + (animationDuration / 8);
bool blink = false;
while (tillAnimation > curMillis) {
curMillis = millis();
prevMillis = curMillis;
if (blinkTimer < curMillis) {
if (blink) { // jika mati
for (int i = 0; i < width; i++) {
int r = pos + i;
int c = currow;
mx.setPoint(r, c, true);
mx.setPoint(r, c + 1, true);
}
blink = false;
blinkTimer = curMillis + (animationDuration / 8);
if (buzzerPin != -1) {
tone(buzzerPin, 262, (animationDuration / 8));
}
} else {
for (int i = 0; i < width; i++) {
int r = pos + i;
int c = currow;
mx.setPoint(r, c, false);
mx.setPoint(r, c + 1, false);
}
if (buzzerPin != -1) {
tone(buzzerPin, 288, (animationDuration / 8));
}
blink = true;
blinkTimer = curMillis + (animationDuration / 8);
}
}
}
}
void animatedrop(int pos, int width, bool isFail) { // Ini hanya dipanggil jika gagal
Serial.println("Gagal");
unsigned long tillAnimation = curMillis + animationDuration;
unsigned long blinkTimer = curMillis + (animationDuration / 8);
unsigned int buzz = 600;
unsigned int buzzI = 10;
bool blink = false;
while (tillAnimation > curMillis) {
curMillis = millis();
prevMillis = curMillis;
if (blinkTimer < curMillis) {
if (blink) { // jika mati
for (int i = 0; i < width; i++) {
int r = pos + i;
int c = currow;
mx.setPoint(r, c, true);
mx.setPoint(r, c + 1, true);
}
blink = false;
blinkTimer = curMillis + (animationDuration / 8);
} else {
for (int i = 0; i < width; i++) {
int r = pos + i;
int c = currow;
mx.setPoint(r, c, false);
mx.setPoint(r, c + 1, false);
}
blink = true;
blinkTimer = curMillis + (animationDuration / 8);
}
if (buzzerPin != -1) {
tone(buzzerPin, buzz, (animationDuration / 8));
}
buzz -= buzzI;
}
}
}
void buttonPressed() {
if (value == HIGH) {
jeda = 1;
clicked = true;
buttonwait = curMillis;
} else if (value == LOW && game == 1) {
if (!clicked) {
if (currow != bottom) {
if (checkAir()) {
return;
}
} else {
if (buzzerPin != -1) {
tone(buzzerPin, 1000, 100);
}
}
prevcurpos = curpos;
// Serial.print("prevcurpos = "); Serial.println(prevcurpos);
currow += 2;// Bergerak ke atas pada baris
if (currow > ((top / 4) + 1) && cursize == 3) {
cur = 1;
cursize--;
} else if (currow > ((top / 2) + 2) && cursize == 2) {
cur = 1;
cursize--;
} else {
cur = 0;
}
// Serial.print("cur = "); Serial.println(cur);
onUpdate();
intervalModifier = random(5, 11) * 5; // Rentang 25 (5*5) hingga 50 (10*5)
interval -= intervalModifier;
if (interval < maxSpeed) { // Pencegahan agar tidak melewati kecepatan maksimum
interval = maxSpeed;
}
// Serial.print("intervalModifier =>"); Serial.print(intervalModifier);
// Serial.print("|| interval =>"); Serial.println(interval);
clicked = true;
buttonwait = curMillis;
}
}
}
void arrow() {
Serial.println("arrow");
for (int j = -35; j < 40; j++) {
for (int i = 0; i < 10; i++) {
int offset = i * 3; // Menghitung jarak antar pola
// Menggambar pola utama
mx.setPoint(1, j + offset, true);
mx.setPoint(6, j + offset, true);
mx.setPoint(2, j + 1 + offset, true);
mx.setPoint(5, j + 1 + offset, true);
mx.setPoint(3, j + 2 + offset, true);
mx.setPoint(4, j + 2 + offset, true);
// Menghapus jejak yang sudah terlalu lama
if (j - 1 >= -40) {
mx.setPoint(1, j - 1 + offset, false);
mx.setPoint(6, j - 1 + offset, false);
mx.setPoint(2, j - 1 + 1 + offset, false);
mx.setPoint(5, j - 1 + 1 + offset, false);
mx.setPoint(3, j - 1 + 2 + offset, false);
mx.setPoint(4, j - 1 + 2 + offset, false);
}
}
delay(10);
}
}
void loop()
{
unsigned long currentMillis = millis();
curMillis = millis();
value = digitalRead(BUTTON_PIN);
if (value != lastState && push == false) {
lastState = value;
buttonPressed();
}
if (millis() - lastButtonPressTime > 1000 ) {
if (game == 1) {
jeda++;
}
lastButtonPressTime = millis();
}
if (jeda >= waktustandby ) {
jeda = 1;
anim = random(1, 3);
game = 0;
push = 0;
Serial.print("Animasi = "); Serial.println(anim);
currentState = 3;
previousMillis = currentMillis;
}
if (clicked && value == lastState ) {
if (game == 0) {
currentState = 1;
jeda = 1;
Serial.println("GAME READY");
}
if (curMillis - buttonwait >= 50) {
clicked = false;
}
}
if (currow >= win) { //maxHeight
currow = bottom;
winState();
}
switch (currentState) {
case 0:
push = 0;
if (game == 0) {
switch (anim) {
case 1:
v_pingpong("STACKER", 100);
rainbowCycle(scrl, 150);
break;
case 2:
v_1huruf(" S T A C K E R ", 500);
rainbowBreath(500);
break;
default:
v_pingpong("STACKER", 100);
rainbowCycle(scrl, 150);
break;
}
} else {
v_pingpong("stacker", 100);
rainbowCycle(scrl, 150);
}
break;
case 1:
push = 1;
arrow();
for (int i = 3; i > 0; i--) {
P.print(i); // Menampilkan angka
delay(1000); // Tunggu 1 detik
mx.clear(); // Bersihkan layar
delay(200); // Tunggu 0.5 detik sebelum angka berikutnya
}
game = 1;
resetGame();
currentState = 2;
Serial.println("START GAME");
break;
case 2:
push = 0;
if (curMillis - prevMillis >= interval) { // Jika interval antara pembaruan telah tercapai
onUpdate(); // Pembaruan
}
break;
case 3:
push = 1;
for (int i = 0; i < 3; i++) {
for (int r = 0; r < MATRIX_WIDTH; r++) {
for (int c = 0; c < MATRIX_HEIGHT; c++) {
mx.setPoint(r, c, true); // Nyalakan titik LED di (row, col) pada modul i
}
}
delay(50);
mx.clear();
delay(50);
}
game = 0;
push = 0;
currentState = 0;
break;
case 4:
P.print("win");
if (digitalRead(BUTTON_PIN) == false) {
Serial.print("klik ");
currentState = 1;
}
// Serial.print("push = "); Serial.println(push);
break;
}
// Serial.print("jeda = "); Serial.print(jeda); Serial.print(" || currentState = "); Serial.print(currentState); Serial.print(" || game = "); Serial.print(game); Serial.print(" || push = "); Serial.println(push);
}
void ledclear() {
for (uint8_t i = 0; i < strip.numPixels(); i++) {
strip.setPixelColor(i, strip.Color(0, 0, 0));
strip.show();
}
}
void rainbowCycle(bool s, uint16_t w) {
static uint8_t j = 0;
if (millis() - waktu_led >= w) {
waktu_led = millis();
// Serial.print("index led= "); Serial.println(index_led);
if (s == 0) {
strip.setPixelColor(index_led, strip.Color(255, 255, 255));
strip.setPixelColor(index_led - 1, Wheel((index_led + j) & 255));
index_led++;
} else {
strip.setPixelColor(index_led, strip.Color(255, 255, 255));
strip.setPixelColor(index_led + 1, Wheel((index_led + j) & 255));
index_led--;
}
strip.show();
if (index_led > TOTAL_LED - 1) {
index_led = 0;
strip.setPixelColor(TOTAL_LED - 1, Wheel((index_led + j) & 255));
}
if (index_led < 0) {
index_led = TOTAL_LED - 1;
strip.setPixelColor(0, Wheel((index_led + j) & 255));
}
j++;
if ( j > 255) {
j = 0;
}
}
}
void rainbowBreath(uint16_t w) {
static uint8_t j = 0;
static uint8_t b = 0;
unsigned long wkt = 0;
if (millis() - wkt >= w) {
wkt = millis();
b++;
}
if (millis() - waktu_led >= 75) {
waktu_led = millis();
for (int i = 0; i < TOTAL_LED; i++) {
// Hitung warna untuk setiap LED berdasarkan offset
uint32_t color = Wheel((i + j) & 255);
strip.setPixelColor(i, color);
}
strip.show();
j++;
if ( j > 255) {
j = 0;
}
}
strip.setBrightness(b);
if (b > 255) {
b = 0;
}
}