Making Flappy Bird in my Game Engine. How hard can it be? - [Helicity.ai Part 3]

lilshake

Abhishek

Posted on July 8, 2023

Making Flappy Bird in my Game Engine. How hard can it be? - [Helicity.ai Part 3]

Hello everyone! ๐Ÿ™‹โ€โ™‚๏ธ I thought I'd share my latest game development adventure with you all. Recently, I thought to myself, "Making Flappy Bird in my own game engine? How hard can it be?" ๐Ÿค”

I learned a lot of things I need to add to my Engine.

Helicity.ai is my Game Engine.

Here is the source ๐Ÿ˜บgithub

Image description

Step by Step Guide

Step 1: Importing the Necessary Modules ๐Ÿ“š

// Import modules
import { GameObject } from "./Gameobject.js";
import { Input } from "./Input.js";
import { Physics } from "./Physics.js";
import { Renderer } from "./Renderer.js";
import { Game } from "./Engine.js";
Enter fullscreen mode Exit fullscreen mode

First things first, we need to import our modules! They're the backbone of our game and do a ton of heavy lifting for us. ๐Ÿ‹๏ธโ€โ™€๏ธ
You can see what every module does on the github link. But they handle specific sections of the game.

Step 2: Setting Up the Bird ๐Ÿค

var score = 0;
// Create Bird class that extends GameObject
class Bird extends GameObject {
  constructor(x, y, width, height, imageSrc) {
    super(x, y, width, height, "bird", imageSrc);
    this.velocityY = 0;
    this.gravity = 0.3;
  }

    // Check for input to control the bird
    if (Input.getState().keys["space"] || Input.getState().mouseLeftDown) {
      this.velocityY = -7;
    }

    //draw score 
    Renderer.drawText("Score: "+score,30,30,25,"black","Arial")
  }
}
Enter fullscreen mode Exit fullscreen mode

The GameObject is a Class which takes in constructor (x, y, width, height, some-type-tag, image-source) The game engine is build around playing with these instances and their update() methods, that have the frame wise logic.

Here, we're creating a Bird class that extends our GameObject.
The bird is the main object of our game! ๐ŸŒŸ We're giving it a velocity and gravity property to handle its movement. ๐ŸŒ
Also I'm drawing the score property.

We don't REALLLY need a class for the Bird because it will only have 1 instance but I guess that's good practice?

Step 3: Moving the Bird ๐Ÿ•น

Inside our Bird class, we also have an update function. This is where all the magic happens - we update the bird's position, check for collisions, and handle user input. ๐ŸŽฎ
Basic rectangular collisions are handled by Physics.checkCollision(gameobject1 , gameobject2)

class Bird extends GameObject {
  constructor(x, y, width, height, imageSrc) {
    super(x, y, width, height, "bird", imageSrc);
    this.velocityY = 0;
    this.gravity = 0.3;
  }

  update() {
    // Apply gravity
    this.velocityY += this.gravity;
    this.y += this.velocityY;

    // Check for collision with pipes
    for (const pipe of Game.gameObjects) {
      if (pipe.type === "pipe" && Physics.checkCollision(this, pipe)) {
        Game.stop();
        Renderer.drawText("Game Over", 100, 100, 30, "black", "Arial");
      }
    }

    // Check for input to control the bird
    if (Input.getState().keys["space"] || Input.getState().mouseLeftDown) {
      this.velocityY = -7;
    }

    //draw score 
    Renderer.drawText("Score: "+score,30,30,25,"black","Arial")
  }
}
Enter fullscreen mode Exit fullscreen mode

Step 4: Creating the Pipes ๐ŸŒ†

// Create Pipe class that extends GameObject
class Pipe extends GameObject {
  constructor(x, y, width, height, imageSrc) {
    super(x, y, width, height, "pipe", imageSrc);
    this.velocityX = -2;
  }

  update() {
    this.x += this.velocityX;

    // Remove pipe when it goes off the screen
    if (this.x + this.width < 0) {
      Game.gameObjects.splice(Game.gameObjects.indexOf(this), 1);
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Next up are our infamous pipes! Just like our bird, we create a Pipe class that extends GameObject. We're giving each pipe a constant velocity to make it move. ๐Ÿ™

Step 5: Adding Our Bird ๐ŸŽฒ

After creating our classes, it's time to instantiate our bird or any other game objects and add them to our game ๐Ÿงฉ. I just picked up some png from Google.

const bird = new Bird(100, 200, 50, 50, "https://freepngimg.com/thumb/logo/109941-logo-bird-flappy-free-transparent-image-hq.png");

Enter fullscreen mode Exit fullscreen mode

Step 6: Spawning the Pipes โฑ

We're using a setInterval function to spawn our pipes every two seconds. Every time a new set of pipes is spawned, our score increases. ๐Ÿ“ˆ

// Create pipes every second
setInterval(() => {
  if(Game.isRunning){
    score++;
  }
  const pipeTop = new Pipe(Renderer.canvas.width, 0, 100, Math.random() * 200 + 100, "https://upload.wikimedia.org/wikipedia/commons/9/93/Mario_pipe.png");
  const pipeBottom = new Pipe(Renderer.canvas.width, pipeTop.height + 300, 100, 600 - pipeTop.height - 200, "https://upload.wikimedia.org/wikipedia/commons/9/93/Mario_pipe.png");
  Game.gameObjects.push(pipeTop, pipeBottom);
}, 2000);
Enter fullscreen mode Exit fullscreen mode

Image description

This is when I realised I need xscale and yscale properties ASAP in my game object, I mean look at how the pipes are spawning!

Conclusions

Finally, we start our game with Game.start(). Now, I can tell people I made flappy bird in my own engine! ๐ŸŽ‰

But honestly its more about improving the engine and what this taught me. If I need to make this a real thing, it needs to be usable. Also we need a background component.

So that's it! Creating a Flappy Bird clone in my game engine turned out to be a fun and enlightening experience! ๐ŸŽˆ๐ŸŽŠ I hope you found this post helpful and inspiring. Don't hesitate to reach out if you have any questions or comments. Happy coding! ๐Ÿš€๐Ÿš€๐Ÿš€

Discord link - Support Development

Discord

๐Ÿ’– ๐Ÿ’ช ๐Ÿ™… ๐Ÿšฉ
lilshake
Abhishek

Posted on July 8, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

ยฉ TheLazy.dev

About