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
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";
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")
}
}
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")
}
}
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);
}
}
}
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");
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);
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! ๐๐๐
Top comments (2)
hmm,Your game engine needs more features๐.
True that!