// 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 #include #include #include #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); } }