ferrybig icon

Arduino Stacker Game

ferrybig | PRO | 01/27/20 04:24:16 PM UTC | 0 ⭐ | 743 👁️ | Never ⏰ | []
C++ |

4.31 KB

|

None

|

0 👍

/

0 👎

// https://www.reddit.com/user/ferrybig
/*  OLED SSD1306 <-> Arduino (nano/uno)
     D0--------------10
     D1--------------9
     RST-------------13
     DC--------------11
     VCC-------------5V
     GND-------------GND
     CS--------------12
    Others:
     Button active low: 2
     > Used for placing the blocks
     Led active high: A5 (Optional)
     > Used for death indication
     Buzzer: 3 (Optional)
     > Feedback for button press
 */
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
 
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
 
// Declaration for SSD1306 display connected using software SPI (default case):
#define OLED_MOSI   9
#define OLED_CLK   10
#define OLED_DC    11
#define OLED_CS    12
#define OLED_RESET 13
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT,
  OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);
 
const int pin_button = 2;
const int pin_led = A5;
const int pin_buzzer = 3;
 
const int initial_delay_timer = 32;
const int initial_x = 32;
const int initial_width = 8;
const int height = 4;
const int initial_y = 128 - height;
const int speed = 2;
 
int valid_x = 0;
int x = initial_x;
int width = initial_width;
int y = initial_y;
bool direction_inverse = false;
bool has_released = false;
bool first_block = true;
int delayTimer = initial_delay_timer;
bool game_over = false;
 
 
void setup() {
    // put your setup code here, to run once:
 
    Serial.begin(9600);
    pinMode(pin_button, INPUT_PULLUP);
    pinMode(pin_led, OUTPUT);
    pinMode(pin_buzzer, OUTPUT);
 
    ADCSRA = 0; // We don't need analog read functionality in this project
    
    // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
    if(!display.begin(SSD1306_SWITCHCAPVCC)) {
        Serial.println(F("SSD1306 allocation failed"));
        for(;;); // Don't proceed, loop forever
    }
    display.clearDisplay();
    //display.invertDisplay(true);
    draw();
}
 
void restart() {
    //digitalWrite(pin_reset, LOW); // Reset arduino
    //pinMode(pin_reset, OUTPUT);
    y = initial_y;
    x = initial_x;
    width = initial_width;
    delayTimer = initial_delay_timer;
    first_block = true;
    display.clearDisplay();
    //display.invertDisplay(true);
}
 
void gameOver() {
    game_over = true;
    digitalWrite(pin_led, HIGH);
    // Wait till button is released
    while(digitalRead(pin_button) == LOW);
    
    while(true) {
        fillRect(x, y, width, height, SSD1306_INVERSE);
        display.display();
        delay(100);
        if(digitalRead(pin_button) == LOW) {
            restart();
            break;
        }
    }
    digitalWrite(pin_led, LOW);
}
 
void fillRect(int x, int y, int width, int height, int color) {
    // Perform screen rotation here
    display.fillRect(128 - y - height, x, height, width, color);
}
 
void input() {
    if (digitalRead(pin_button) == LOW) {
        if(has_released) {
            if(first_block) {
                valid_x = x;
                first_block = false;
            } else {
                const int old_width = width;
                if(x + width < valid_x) {
                    // ##
                    //   ##
                    gameOver();
                } else if (x + width < valid_x + width) {
                    // ##
                    //  ##
                    width = width - (valid_x - x);
                } else if (x < valid_x + width) {
                    //   ##
                    //  ##
                    width = valid_x + width - x;
                    valid_x = x;
                } else {
                    //   ##
                    // ##
                    gameOver();
                }
                if(width == 0) {
                    // strange bug
                    width = old_width;
                    gameOver();
                }
            }
            has_released = false;
            if(!game_over) {
                fillRect(valid_x, y, width, height, SSD1306_INVERSE);
                if(y == 0) {
                    // win
                }
                y -= height;
                delayTimer--;
            } else {
                game_over = false;
            }
            tone(pin_buzzer, 3000, 10);
        }
    } else {
        has_released = true;
    }
}
 
void update() {
    if(direction_inverse) {
        if(x == 0) {
            direction_inverse = false;
        } else {
            x -= speed;
        }
    } else {
        if(x == 64 - width) {
            direction_inverse = true;
        } else {
            x += speed;
        }
    }
}
 
void draw() {
    fillRect(x, y, width, height, SSD1306_INVERSE);
}
 
void clearDraw() {
    fillRect(x, y, width, height, SSD1306_INVERSE);
}
 
void loop() {
    // put your main code here, to run repeatedly:
    clearDraw();
    input();
    update();
    draw();
    display.display();
    if(delayTimer > 1) {
        delay(delayTimer);
    }
}

Comments