#include <Adafruit_NeoPixel.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Bounce2.h>
// Pin Definitions
#define BUTTON_START_PIN 2
#define BUTTON_RESET_PIN 4
#define BUZZER_PIN 3
#define LED_RING_PIN 6
#define NUM_LEDS 24
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
// Create NeoPixel instance
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, LED_RING_PIN, NEO_GRB + NEO_KHZ800);
// Create OLED instance
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
// Button debounce
Bounce debouncerStart = Bounce();
Bounce debouncerReset = Bounce();
// Game variables
bool rouletteActive = false;
int randomPosition = 0;
int selectedNumber = 0;
int playerScore = 0;
int playerBet = 0; // Default bet is zero
int minBet = 1; // Minimum bet
int maxBet = 100; // Maximum bet
unsigned long betAmount = 10; // Default bet amount
String bettingHistory[10]; // Store last 10 bets
int historyIndex = 0; // Current index for history
void setup() {
// Initialize pin modes
pinMode(BUTTON_START_PIN, INPUT_PULLUP);
pinMode(BUTTON_RESET_PIN, INPUT_PULLUP);
pinMode(BUZZER_PIN, OUTPUT);
// Initialize debounce
debouncerStart.attach(BUTTON_START_PIN);
debouncerStart.interval(5);
debouncerReset.attach(BUTTON_RESET_PIN);
debouncerReset.interval(5);
// Initialize NeoPixel strip
strip.begin();
strip.show();
// Initialize OLED
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;);
}
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(WHITE);
// Welcome message on OLED
display.setCursor(0, 0);
display.println("Roulette Game");
display.display();
delay(2000);
display.clearDisplay();
}
void loop() {
// Update button states
debouncerStart.update();
debouncerReset.update();
// If reset button is pressed
if (debouncerReset.fell()) {
resetGame();
}
// If start button is pressed and game is not active
if (debouncerStart.fell() && !rouletteActive) {
selectBet();
}
// If roulette is active, display spin animation on OLED
if (rouletteActive) {
spinAnimation();
}
}
void selectBet() {
display.clearDisplay();
display.setCursor(0, 0);
display.setTextSize(2);
display.print("Select Bet: ");
for (int i = minBet; i <= maxBet; i++) {
display.setCursor(0, 30 + (i - minBet) * 10);
display.print(i);
}
display.display();
// Wait for player to select a bet (minBet to maxBet)
while (true) {
debouncerStart.update();
if (debouncerStart.fell()) {
playerBet = (playerBet % (maxBet - minBet + 1)) + minBet; // Rotate bet selection
display.setCursor(0, 30 + (playerBet - minBet) * 10);
display.print(">"); // Highlight selected number
display.display();
delay(200); // Debounce delay
}
if (debouncerReset.fell()) {
resetGame();
return; // Reset the game if reset button is pressed
}
if (debouncerStart.fell() && !rouletteActive) {
startRoulette();
break;
}
}
}
void startRoulette() {
rouletteActive = true;
randomPosition = random(0, NUM_LEDS); // Randomize LED position
selectedNumber = random(1, NUM_LEDS + 1); // Randomize result number (1-24)
// Start spinning roulette with smoother animation
for (int i = 0; i < 200; i++) {
showLED(i % NUM_LEDS); // Show each LED in sequence
delay(30 + (i / 5)); // Increase delay for smoother transition
}
// Final sound and display result
tone(BUZZER_PIN, 1500, 200); // Final sound
showLED(randomPosition); // Light up final LED
displayResult();
rouletteActive = false;
}
void showLED(int pos) {
// Turn off all LEDs
strip.clear();
// Light up the selected LED
strip.setPixelColor(pos, strip.Color(255, 0, 0)); // Red color for selected LED
strip.show();
}
void displayResult() {
// Clear OLED and display the result
display.clearDisplay();
display.setTextSize(2);
display.setCursor(0, 0);
display.print("Result: ");
display.println(selectedNumber);
display.setTextSize(1);
display.setCursor(0, 40);
display.print("Your Bet: ");
display.println(playerBet);
// Display player's current score
display.setCursor(0, 50);
display.print("Score: ");
display.println(playerScore);
// Log the betting history
logBettingHistory(selectedNumber, playerBet);
// Show win/lose animation
if (selectedNumber == playerBet) {
playerScore += betAmount; // Update score for winning
displayWinAnimation();
} else {
playerScore -= betAmount; // Update score for losing
displayLoseAnimation();
}
}
void spinAnimation() {
// Display "spinning" animation on OLED
display.clearDisplay();
display.setTextSize(1);
display.setCursor(0, 0);
display.println("Spinning...");
// Display a spinning bar animation
int barLength = 5;
int barPos = (millis() / 100) % (SCREEN_WIDTH - barLength);
display.fillRect(barPos, SCREEN_HEIGHT / 2, barLength, 10, WHITE);
display.display();
}
void logBettingHistory(int result, int bet) {
// Store betting history
bettingHistory[historyIndex] = "Bet: " + String(bet) + " Result: " + String(result);
historyIndex = (historyIndex + 1) % 10; // Circular buffer
}
void displayWinAnimation() {
// Play win sound and flash LEDs
for (int i = 0; i < 5; i++) {
tone(BUZZER_PIN, 1000, 100);
strip.fill(strip.Color(0, 255, 0)); // Green for win
strip.show();
delay(200);
strip.clear();
strip.show();
delay(200);
}
// Update OLED display with score
display.clearDisplay();
display.setTextSize(2);
display.setCursor(0, 0);
display.println("You Win!");
display.setTextSize(1);
display.setCursor(0, 30);
display.print("Score: ");
display.println(playerScore);
display.display();
}
void displayLoseAnimation() {
// Play lose sound and flash LEDs
for (int i = 0; i < 3; i++) {
tone(BUZZER_PIN, 500, 100);
strip.fill(strip.Color(255, 0, 0)); // Red for lose
strip.show();
delay(200);
strip.clear();
strip.show();
delay(200);
}
// Update OLED display with score
display.clearDisplay();
display.setTextSize(2);
display.setCursor(0, 0);
display.println("You Lose!");
display.setTextSize(1);
display.setCursor(0, 30);
display.print("Score: ");