Introduction

 

     When I wanted to build a project for the NanoRama Project14 contest, FlappyRama wasn't my initial idea to build upon. But with unprecedented turn of events, I ended up with FlappyRama a fun little game which everyone can build on their own and have fun.

 

     Due to lock down in our country, I was confined to my home town away from my workplace, 3D printer and all my electronics. So all I had was an Arduino Nano 33 IoT board and a personal computer with me for doing a project. Adding to the limitation, Arduino Nano 33 IoT has only 6-axis IMU LSM6DS3 and no other sensors like temperature, or humidity to build something like a cool IoT Dashboard.

 

     I started working on building a gesture detection powered by Azure ML with Arduino Nano 33 IoT, but time was a constraint and it took me longer than I expected. Then this idea popped up, FlappyRama. It is a Flappy Bird like game developed in Processing. Normally Flappy Bird game takes mouse click as an input. So instead of that, I replaced it with Arduino Nano 33 IoT board and its 6-axis IMU. Read more details on the project in the following section.

 

     Thanks to tariq.ahmad and Element14 Community team for sending me an Arduino and also for the deadline extension till May 18th - click here.

 

Nano 33 IoT

 

FlappyRama - The Game

 

     Almost every one would have played 'Flappy Bird' game (https://flappybird.io/ ) at least once. It is simple, fun and easy to play game. So this game has two parts - the game developed on Processing and the controller using Arduino Nano 33 IoT.

 

  • The Game - Using processing we can build cool 2D, 3D graphics projects in Java, Python which can be used along side with electronics. As the original game, this game has the character 'Flappy bird' which navigates itself through a set of barriers. On successfully passing through one, the player gains a point which is added to his total score. Player has to keep the bird flying and make sure not to hit any of the barriers. In the original game, a mouse click will control the bird, but in this project, Arduino Nano 33 IoT acts as the controller.
  • The Controller - Arduino Nano 33 IoT board comes with 6-axis IMU LSM6DS3 which gives us the x, y, z co-ordinates of the board. This game is 2D and since the bird either flies up or down, we would need only y-axis. So if y-axis crosses a particular point we'll consider it as like a click-event in a mouse and serially communicate with the Processing game. This serial event will keep the Flappy bird flying.

 

     Below is the demo video of me playing the FlappyRama game using Arduino Nano 33 IoT board.

 

 

Code

 

Arduino Code

 

#include <Arduino_LSM6DS3.h>
float x, y, z;


void setup() {
  Serial.begin(9600);


  pinMode(LED_BUILTIN, OUTPUT);
  
  if (!IMU.begin()) {
    Serial.println("Failed to initialize IMU!");


    while (1);
  }
}


void loop(){
  if (IMU.accelerationAvailable()) {
    IMU.readAcceleration(x, y, z);


    if(y <= 0.20)
    {
      Serial.println("Board has been lifted");
      digitalWrite(LED_BUILTIN, HIGH);
    }
    else
    {
      digitalWrite(LED_BUILTIN, LOW);
    }
  }
}

 

Processing Code - Flappy Game

 

import processing.serial.*;


Serial myPort;
flappy f = new flappy();
pipe[] p = new pipe[3];


String myText="";
int lf = 10;
boolean start=true;
boolean end=false;
int points = 0;


void setup(){ 
  //canvas (x,y)
  size(1000, 800);
  
  for(int i=0; i<3; i++){
    p[i] = new pipe(i);
  }
  
  myPort = new Serial(this, "COM5", 9600);
  myPort.bufferUntil(lf);
}


void serialEvent (Serial myPort){
  myText = myPort.readStringUntil(lf);
  //text(myText, 50, 50);
  action();
}


void draw(){
  initializeScreen();
  if(end){
    f.move();
  }
  
  f.drawFlappy();
  
  if(end){
    f.drag();
  }
  
  f.checkCollisions();
  for(int i = 0;i<3;i++){
    p[i].drawPipe();
    p[i].checkPosition();
    strokeWeight(10);
  }
}


class flappy{
  float flappyX, flappyY, flappySpeed;
  
  flappy(){
    flappyX = 50; flappyY = 200;
  }
  
  void drawFlappy(){
    //body
    stroke(#FEFF03);
    fill(#FEFF03);
    strokeWeight(1);
    ellipse(flappyX, flappyY, 15, 15);
    
    //eye
    stroke(255);
    fill(255);
    strokeWeight(1);
    ellipse(flappyX+5, flappyY-2, 7.5, 7.5);
    
    //eyeball
    stroke(0);
    fill(0);
    strokeWeight(1);
    ellipse(flappyX+7, flappyY-2, 2.5,2.5);
    
    //mouth
    stroke(#FF2903);
    fill(#FF2903);
    strokeWeight(1);
    ellipse(flappyX+5, flappyY+5, 8, 4);
    
    //wing
    stroke(#DADB0F);
    fill(#DADB0F);
    strokeWeight(1);
    ellipse(flappyX-10, flappyY+2, 10, 6);
  }
  
  void fly(){
    flappySpeed -= 1;
  }
  
  void drag(){
    flappySpeed += 0.1;
  }
  
  void move(){
    flappyY += flappySpeed;
    for(int i=0; i<3; i++){
      p[i].pipeX -= 3;
    }
  }
  
  void checkCollisions(){
     if(flappyY > 800){
       end = false;
     }
    for(int i=0; i<3; i++){
      if((flappyX < p[i].pipeX + 10 && flappyX > p[i].pipeX - 10) && (flappyY < p[i].gap - 100 || flappyY > p[i].gap + 100)){
        end=false; 
      }
    }
  }
}


class pipe{
  float pipeX, gap;
  boolean crashed = false;
  
  pipe(int i){
    pipeX = 100 + (i * 200);
    gap = random(600) + 100;
    strokeWeight(10);  
  }
  
  void drawPipe(){
    stroke(#21F207);
    fill(#21F207);
    strokeWeight(10);  
    line(pipeX, 0, pipeX, gap - 100);
    
    stroke(#21F207);
    fill(#21F207);
    strokeWeight(10);
    line(pipeX, gap + 100, pipeX, 800);  
  }
  
  void checkPosition(){
    if(pipeX < 0){
      pipeX += (200*3);
      gap = random(600) + 100;
      crashed=false;
    } 
    if(pipeX < 150 && crashed == false){
      crashed=true;
      points++; 
    }
  }
}


void reset(){
  end = true;
  points = 0;
  f.flappyY = 200;
  for(int i=0; i<3; i++){
    p[i].pipeX += 550;
    p[i].crashed = false;
  }
}


void initializeScreen(){
  //background color
  background(#0CABE8); //skyblue
  
  //points
  textSize(20);
  score();
}


void score(){
  stroke(#0CABE8);
  fill(#0CABE8);
  rect(width-170, 5, 165, 25);
  
  stroke(0);
  fill(0);
  text("Score:", width-150, 25);
  text(points, width-80, 25);
}


void mousePressed(){
  action();
}


void action(){
  f.fly();
  score();
  start = false;
  if(end == false){
    reset();
  }
}

 

 

Credits

 

Processing code for the 'FlappyRama' Game was built upon and remixed from 'Flappy Code' by 'Dr. J' sketch here in https://www.openprocessing.org/sketch/748493 under Creative Commons Attribution ShareAlike