Tag: coding

  • Y0/FMCC/W3 – Flappy Bird 0

    This week I am looking at interaction in p5. I wanted to code a simple ‘jump’ game. Something that could be done in less than an hour so: Flappy Bird.

    Setup

    I first declare some needed variables:

    const speed = 3;
    let score = 0;
    let highscore = 0;
    
    function setup() {
      createCanvas(400, 400);
      strokeWeight(0);
      textAlign(CENTER,CENTER)
      
      thefloor = height;
      theceiling = 0;
    }

    Speed will be used to determine the difficulty of the game. Pipes will move at this speed. I set it as a constant but if I wanted to make the difficulty variable I could declare it using ‘let’.

    player object

    I first created the player object. I called it ‘frog’ because it jumps though I should have probably called it bird.

    To create an object in JavaScript is simple. I simply need to declare it as a class and write the constructor method.

    class freg{
      constructor(){
        this.x = width/2;
        this.y = height/2;
        this.yvel = 0;
        this.pressed = false;
      }
    }

    I am giving my player a position (x,y) and y-velocity. I am also setting a variable to determine whether an input was given.

    I will next add a drawself() method

    drawself(){
      circle(this.x,this.y,32);
    }

    and a step() method. This will run every frame.

    step(){
      this.yvel -= 0.2; //gravity
      if(keyIsPressed && !this.pressed){
        this.pressed = true;
        if(keyCode == 32){
          this.yvel = 4;
        }
      }
      if(!keyIsPressed){ this.pressed = false; }
    
      this.y = (this.y - this.yvel) //apply movement
      
      if(this.y < theceiling || this.y >= thefloor){
        this.die();
      };
      this.drawself(); //draw
    }

    The step method includes gravity calculation and input handling. When a key is being pressed and the flag for already having pressed that key is not set, it will grant the player some upwards velocity.

    The step method also handles crashing into the ceiling and floor.

    The final thing it does is call the ‘die’ method.

    die(){
      score = 0;
      this.y = height/2;
      this.yvel = 0;
    
      pipes.x = width;
      pipes.hei = random(height);
      pipes.cleared = false;
    }

    Dying will reset the score and position of the player/pipes.

    Pipes

    I’m defining pipes as a single object with height, width and gap. These will affect the pipe object as such:

    Made using Aseprite
    class pipe{
      constructor(hei,gap){
        this.hei = hei;
        this.gap = gap;
        this.x = width;
        
        this.wid = 64;
        this.cleared = false;
      }
    }

    The draw function is slightly more involved than drawing the player. It draws two rectangles for each pipe (top and bottom).

    drawself(){
      rect(this.x,0,this.wid,this.hei-this.gap/2);
      rect(this.x,this.hei+this.gap/2,this.wid,height);
    }

    The step function handles collision checking and increasing the score when the player successfully flies through the gap. It also moves the pipe to the right of the canvas when it is fully off-screen to the left.

    step(){
      this.drawself(); //draw
      this.x -= speed;
        
      if(this.x < -64){
        this.x = width;
        this.hei = random(height);
        this.cleared = false;
      }
      
      if(frog.x > this.x &&
        frog.x < this.x + this.wid &&
        frog.y > 0 &&
        frog.y < this.hei-(this.gap/2)){
        
        frog.die();
      }
      if(frog.x > this.x &&
        frog.x < this.x + this.wid &&
        frog.y > this.hei+this.gap/2 &&
        frog.y < height){
        
        frog.die();
      }
        
      if(this.x+this.wid < frog.x && this.cleared == false){ 
        this.cleared = true; 
        score++;
      }
    }

    Causing the pipes to wrap around means that there doesn’t need to be multiple pipe objects, just one which reduces memory usage and lag.

    Final Steps

    All that remains is to assign the two objects to variables in the setup function

    function setup() {
      ...
      frog = new freg();
      pipes = new pipe(200,128); 
    }

    And step them in the draw function. I will also add some logic to deal with scoring.

    function draw() {
      background(220);
      
      highscore = max(score,highscore);
      textSize(100);
      text(score,width/2,64);
      textSize(32);
      text("HI: "+highscore,width/2,128)
      
      frog.step();
      pipes.step();
    }

    The game is complete.

    Made using p5.js

    Link to Project/ Code

    https://editor.p5js.org/woojinJang_/sketches/RV2tZzt4h