Making a game
Now that we can detect joystick presses and output to the OLED display, we’ve got all we need to make a simple game.
The code below is a simplified version of Flappy Bird where you have to push the joystick to jump through gaps in pipes that scroll across the screen.
#include <OLEDDisplay.h> #include <SSD1306.h> // connect to display using pins D1, D2 for I2C on address 0x3c SSD1306 display(0x3c, D1, D2); // flappy dot variables int x, y, score; float fy = 0; float velocity = 0; float gravity = 0.4; // joystick pins and presses byte joystick_pins[] = {D3, D5, D6, D7}; byte joystick_buttons[] = {0, 0, 0, 0}; // joystick pin order constants const byte JOY_RIGHT = 0; const byte JOY_PUSH = 1; const byte JOY_DOWN = 2; const byte JOY_UP = 3; // Draws and manages a pipe obstacle (top and bottom) class Pipe { public: int x,y,gap; // create a new pipe Pipe(int x, int y, int gap){ this->x = x; this->y = y; this->gap = gap; } // draw the pipe to the OLED screen void draw() { // bottom pipe display.drawRect(x, y, 2, 63 - y); display.drawRect(x-2, y-2, 6, 2); // top pipe display.drawRect(x, 0, 2, y - gap); display.drawRect(x-2, y-gap-2, 6, 2); } // move the pipe 1px left void move() { x--; if(x < 0) { x = 128; y = random(32, 64); gap = random(20, 40); } } // check if the dot has collided with this pipe bool hitTest(int birdX, int birdY) { return (x == birdX) && ((birdY > y) || (birdY < y - gap)); } }; void onJoystickChange() { Serial.print("Joystick: "); for(int i = 0; i < sizeof(joystick_pins); i++) { joystick_buttons[i] = !digitalRead(joystick_pins[i]); Serial.print(joystick_buttons[i]); } Serial.println(); } // Create two pipes Pipe *p1; Pipe *p2; void setup() { p1 = new Pipe(64, 25, 30); p2 = new Pipe(128, 64, 30); // init serial port Serial.begin(115200); // set the builtin LED pin to work as an output pinMode(LED_BUILTIN, OUTPUT); for(int i = 0; i < sizeof(joystick_pins); i++) { pinMode(joystick_pins[i], INPUT_PULLUP); attachInterrupt(digitalPinToInterrupt(joystick_pins[i]), onJoystickChange, CHANGE); } // init the display display.init(); // set text x and y coordinate to start at 0 x = 0; y = 0; } bool playing = true; void loop() { // clear the screen display.clear(); // display score display.setTextAlignment(TEXT_ALIGN_LEFT); display.setFont(ArialMT_Plain_10); String str_score = "Score: "; str_score += score; display.drawString(0, 0, str_score); display.setPixel(x, y); // main game actions if(playing) { // push joystick to jump if(joystick_buttons[JOY_PUSH]) velocity = 5; // make dot fall velocity -= gravity; if(velocity < -10) velocity = -10; fy -= (velocity / 10); if(fy > 63) fy = 63; if(fy < 0) fy = 0; y = (int)fy; // make sure x and y are valid numbers if(x > 128) x = 128; if(x < 0) x = 0; // draw pipes p1->draw(); if(p1->hitTest(x, y)) { playing = false; } else { p1->move(); } p2->draw(); if(p2->hitTest(x, y)) { playing = false; } else { p2->move(); } score++; } else { // game over display.drawString(0, 20, "Game over"); } // update the display display.display(); // slow down loop delay(10); }
If this code is useful or you have any questions, please leave a comment below.
Enjoy!
thank you very much for your help 🙂 I couldnt make it work without that
Hiyah!
The directional buttons: FLATH, RSET, D5, D6, D7
What on earth is FLATH?
Also – won’t RSET reset the board when the “direction” is pressed on the little joystick?
Yes, because of the way the joystick is connected up, the board will reset when you press left. I don’t know what FLATH is: it’s on all the description pages when you try to buy it but the joystick is actually connected to D3,D5,D6,D7 (and RSET). Maybe there’s a way to disable the reset-not sure-sorry!
I’m pretty sure FLATH is nothing but a typo from the first and original description (that has been copied wrongly every time)
This is the FLASH button. In order to FLASH another binary (firmware) this button has to be pressed while turning power ON.