#include <U8g2lib.h>
#include <SPI.h>
#include <Wire.h>
// Initialize the display
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
// Pin the flap button is attached to
#define FLAP_BUTTON 2
// Initialize 'sprites'
#define SPRITE_HEIGHT 16
#define SPRITE_WIDTH 16
// Two frames of animation
static const unsigned char PROGMEM wing_down_bmp[] =
{ B00000000, B00000000,
B00000000, B00000000,
B00000011, B11000000,
B00011111, B11110000,
B00111111, B00111000,
B01111111, B11111110,
B11111111, B11000001,
B11011111, B01111110,
B11011111, B01111000,
B11011111, B01111000,
B11001110, B01111000,
B11110001, B11110000,
B01111111, B11100000,
B00111111, B11000000,
B00000111, B00000000,
B00000000, B00000000,
};
static const unsigned char PROGMEM wing_up_bmp[] =
{ B00000000, B00000000,
B00000000, B00000000,
B00000011, B11000000,
B00011111, B11110000,
B00111111, B00111000,
B01110001, B11111110,
B11101110, B11000001,
B11011111, B01111110,
B11011111, B01111000,
B11111111, B11111000,
B11111111, B11111000,
B11111111, B11110000,
B01111111, B11100000,
B00111111, B11000000,
B00000111, B00000000,
B00000000, B00000000,
};
// Game variables
#define GAME_SPEED 50
int game_state = 1; // 0 = game over screen, 1 = in game
int score = 0; // current game score
int high_score = 0; // highest score since the nano was reset
int bird_x = 128 / 4; // birds x position (along) - initialized to 1/4 the way along the screen
int bird_y; // birds y position (down)
int momentum = 0; // how much force is pulling the bird down
int wall_x[2]; // an array to hold the walls x positions
int wall_y[2]; // an array to hold the walls y positions
int wall_gap = 30; // size of the wall gap in pixels
int wall_width = 10; // width of the wall in pixels
void setup() {
Serial.begin(9600);
// Initialize the display
u8g2.begin();
pinMode(FLAP_BUTTON, INPUT_PULLUP);
randomSeed(analogRead(0));
}
void loop() {
if (game_state == 0) {
u8g2.clearBuffer();
if (digitalRead(FLAP_BUTTON) == LOW) {
momentum = -4;
}
momentum += 1;
bird_y += momentum;
if (bird_y < 0 ) {
bird_y = 0;
}
if (bird_y > 64 - SPRITE_HEIGHT) {
bird_y = 64 - SPRITE_HEIGHT;
momentum = -2;
}
if (momentum < 0) {
if (random(2) == 0) {
u8g2.drawXBM(bird_x, bird_y, SPRITE_WIDTH, SPRITE_HEIGHT, wing_down_bmp);
} else {
u8g2.drawXBM(bird_x, bird_y, SPRITE_WIDTH, SPRITE_HEIGHT, wing_up_bmp);
}
} else {
u8g2.drawXBM(bird_x, bird_y, SPRITE_WIDTH, SPRITE_HEIGHT, wing_up_bmp);
}
for (int i = 0 ; i < 2; i++) {
u8g2.drawBox(wall_x[i], 0, wall_width, wall_y[i]);
u8g2.drawBox(wall_x[i], wall_y[i] + wall_gap, wall_width, 64 - wall_y[i] + wall_gap);
if (wall_x[i] < 0) {
wall_y[i] = random(0, 64 - wall_gap);
wall_x[i] = 128;
}
if (wall_x[i] == bird_x) {
score++;
high_score = max(score, high_score);
}
if ((bird_x + SPRITE_WIDTH > wall_x[i] && bird_x < wall_x[i] + wall_width) &&
(bird_y < wall_y[i] || bird_y + SPRITE_HEIGHT > wall_y[i] + wall_gap)) {
u8g2.sendBuffer();
delay(500);
game_state = 1;
}
wall_x[i] -= 4;
}
boldTextAtCenter(0, String(score));
u8g2.sendBuffer();
delay(GAME_SPEED);
} else {
screenWipe(10);
outlineTextAtCenter(1, "NANO BIRD");
textAtCenter(64 / 2 - 8, "GAME OVER");
textAtCenter(64 / 2, String(score));
boldTextAtCenter(64 - 16, "HIGH SCORE");
boldTextAtCenter(64 - 8, String(high_score));
u8g2.sendBuffer();
while (digitalRead(FLAP_BUTTON) == LOW);
bird_y = 64 / 2;
momentum = -4;
wall_x[0] = 128;
wall_y[0] = 64 / 2 - wall_gap / 2;
wall_x[1] = 128 + 128 / 2;
wall_y[1] = 64 / 2 - wall_gap / 1;
score = 0;
while (digitalRead(FLAP_BUTTON) == HIGH);
screenWipe(10);
game_state = 0;
}
}
void screenWipe(int speed) {
for (int i = 0; i < 64; i += speed) {
u8g2.drawBox(0, i, 128, speed);
u8g2.sendBuffer();
}
for (int i = 0; i < 64; i += speed) {
u8g2.clearBuffer();
u8g2.sendBuffer();
}
}
void textAt(int x, int y, String txt) {
u8g2.setCursor(x, y);
u8g2.print(txt);
}
void textAtCenter(int y, String txt) {
textAt(128 / 2 - txt.length() * 3, y, txt);
}
void outlineTextAtCenter(int y, String txt) {
int x = 128 / 2 - txt.length() * 3;
u8g2.setDrawColor(1);
textAt(x - 1, y, txt);
textAt(x + 1, y, txt);
textAt(x, y - 1, txt);
textAt(x, y + 1, txt);
u8g2.setDrawColor(0);
textAt(x, y, txt);
u8g2.setDrawColor(1);
}
void boldTextAtCenter(int y, String txt) {
int x = 128 / 2 - txt.length() * 3;
textAt(x, y, txt);
textAt(x + 1, y, txt);
}