Flying Jack- My first game in Kaboom.js

Inspired by Flappy bird and desire to learn something new

Mithilesh Kr. Patel
6 min readJan 21, 2024

Github repo link : Flying Jack

From childhood, while playing Vice City and GTA games, I used to think of becoming a game developer and create games. As I grew up, I realized the tremendous amount of work that goes into creating even small games like Flappy Bird, not to mention larger ones like GTA.

In the present, I came across a JavaScript library for game development called Kaboom.js (which I had never heard of before). So, I decided to give it a try and see what I could create in just one day, despite having no prior experience in game development.

In this article, I am going to walk you through the steps to create a simple game inspired by Flappy Bird, which I’ve named “Flying Jack.”

Prerequisites: Make sure to have Node.js installed.

Step 1. Setting up Kaboom Development

Using create-kaboom to generate kaboom project

$ npm init kaboom -- mygame

This will create a directory mygame containing everything you need to start a Kaboom project, go to that directory and run npm run dev to start the development server, and edit src/main.js to develop the game.

after running npm run dev a server will get created on http://127.0.0.1:8000/. Go to this url to see your basic game.

Step 2: Lets start editing the main.js

Navigate to the main.js file in src/main.js

Lets add the components one by one. I will explain the use of each line of code.

Starting with the background

import kaboom from "kaboom";

kaboom()

This should give you a blank canvas with a nice blue background like this

Then lets load the game assets. For this game its the smiley, clouds and the sad emoji on the Game Over screen.

loadSprite("bean", "sprites/bean.png");
loadSprite("sad", "sprites/sad.png");
loadSprite("cloud", "sprites/cloud.png");

These are the game constants.

const FLOOR_HEIGHT = 48;
const JUMP_FORCE = 750;
const SPEED = 300;
const GAP_BETN_PIPES = 300;

I have added two screens- one the screen where game runs, second The Game Over screen

scene("game", () => {

// floor
add([
rect(width(), FLOOR_HEIGHT),
outline(4),
pos(0, height()),
anchor("botleft"),
area(),
body({ isStatic: true }),
color(0, 200, 0),
]);

function spawnCloud() {
// CLOUD component

add([
sprite("cloud"),
pos(width(), rand(0, height() - 300)),
area(),
move(LEFT, SPEED-100),
scale(0.3)
]);

wait(1.5, spawnCloud);
}

spawnCloud();

// add a game object to screen
const player = add([
// list of components
sprite("bean"),
pos(200, 40),
area(),
body()
]);

function spawnPipe() {

const HEIGHTOFPIPE = rand(50, 400);

// TOP PIPES
add([
rect(90, height() ),
area(),
outline(4),
pos(width(), height() - FLOOR_HEIGHT - HEIGHTOFPIPE - GAP_BETN_PIPES),
anchor("botleft"),
color(255, 180, 255),
move(LEFT, SPEED),
"tree",
]);

// BOTTOM PIPES
add([
rect(90, HEIGHTOFPIPE),
area(),
outline(4),
pos(width(), height() - FLOOR_HEIGHT),
anchor("botleft"),
color(255, 180, 255),
move(LEFT, SPEED),
"tree",
]);

// wait a random amount of time to spawn next tree
wait(1.5, spawnPipe);

}

// start spawning trees
spawnPipe();


});

This is the Game screen. Above code will add the player, and spawn clouds , and pipes with upside down pipes as well . The move(LEFT, SPEED) will make the clouds and the pipes move towards the LEFT with SPEED pixels per second. In this case it is 300 px per second.

Also we have functions spawnCloud() and spawnPipe() which will spawn pipes at a regular interval of time. The wait(1.5, spawnPipe); functions takes time interval and a callback function as arguments. So in this case, the function spawnPipe() will be called after 1.5 seconds.

Now lets add Gravity into the game.

// define gravity
setGravity(1600);

This will add gravity into the game so that the components like the Player will fall to the ground.

Event handling to Jump on space or mouse click

Now lets add a function so that the Jack can fly when we press Space or click the mouse btn.

function jump() {

player.jump(JUMP_FORCE);

}

// jump when user press space
onKeyPress("space", jump);
onClick(jump);

For Scorekeeping

    // keep track of score
let score = 0;

const scoreLabel = add([
text(score),
scale(2),
pos((width()/2 )-30, 100),
color(rgb(0,0,0))
]);

// increment score every frame
onUpdate(() => {
score++;
scoreLabel.text = score;
});

Adding the Game Over — lose screen with Score

scene("lose", (score) => {

add([
sprite("sad"),
pos(width() / 2, height() / 2 - 80),
scale(2),
anchor("center"),
]);

// display score
add([
text(score),
pos(width() / 2, height() / 2 + 80),
scale(2),
anchor("center"),
color(rgb(0,0,0))
]);

add([
text("Game Over"),
pos(width() / 2, (height() / 2)- 200),
scale(2),
anchor("center"),
color(rgb(0,0,0))
]);

add([
text("Click to play again"),
pos(width() / 2, (height() / 2)+ 120 + 80),
scale(2),
anchor("center"),
color(rgb(0,0,0))
]);

// go back to game with space is pressed
onKeyPress("space", () => go("game"));
onClick(() => go("game"));

});

And finally to start with the game screen, add this as the last line of the program.

go("game");

This this seems too much for you.. Let me give you the whole main.js code.

Full code for main.js

Just replace all the content of main.js with the code below. You can also clone the github repo — Flying Jack

import kaboom from "kaboom";

const FLOOR_HEIGHT = 48;
const JUMP_FORCE = 750;
const SPEED = 300;
const GAP_BETN_PIPES = 300;

// initialize context
kaboom({
background: [51, 151, 255], // Set the background color to RGB [51, 151, 255]
});

// load assets
loadSprite("bean", "sprites/bean.png");
loadSprite("sad", "sprites/sad.png");
loadSprite("cloud", "sprites/cloud.png");

scene("game", () => {

// define gravity
setGravity(1600);

// floor
add([
rect(width(), FLOOR_HEIGHT),
outline(4),
pos(0, height()),
anchor("botleft"),
area(),
body({ isStatic: true }),
color(0, 200, 0),
]);

function jump() {

player.jump(JUMP_FORCE);

}

// jump when user press space
onKeyPress("space", jump);
onClick(jump);


function spawnCloud() {
// CLOUD component

add([
sprite("cloud"),
pos(width(), rand(0, height() - 300)),
area(),
move(LEFT, SPEED-100),
scale(0.3)
]);

wait(1.5, spawnCloud);
}

spawnCloud();

// add a game object to screen
const player = add([
// list of components
sprite("bean"),
pos(200, 40),
area(),
body()
]);

function spawnPipe() {

const HEIGHTOFPIPE = rand(50, 400);

// TOP PIPES
add([
rect(90, height() ),
area(),
outline(4),
pos(width(), height() - FLOOR_HEIGHT - HEIGHTOFPIPE - GAP_BETN_PIPES),
anchor("botleft"),
color(255, 180, 255),
move(LEFT, SPEED),
"tree",
]);

// BOTTOM PIPES
add([
rect(90, HEIGHTOFPIPE),
area(),
outline(4),
pos(width(), height() - FLOOR_HEIGHT),
anchor("botleft"),
color(255, 180, 255),
move(LEFT, SPEED),
"tree",
]);

// wait a random amount of time to spawn next tree
wait(1.5, spawnPipe);

}

// start spawning trees
spawnPipe();


// lose if player collides with any game obj with tag "tree"
player.onCollide("tree", () => {
// go to "lose" scene and pass the score
go("lose", score);

});

// keep track of score
let score = 0;

const scoreLabel = add([
text(score),
scale(2),
pos((width()/2 )-30, 100),
color(rgb(0,0,0))
]);

// increment score every frame
onUpdate(() => {
score++;
scoreLabel.text = score;
});

});

scene("lose", (score) => {

add([
sprite("sad"),
pos(width() / 2, height() / 2 - 80),
scale(2),
anchor("center"),
]);

// display score
add([
text(score),
pos(width() / 2, height() / 2 + 80),
scale(2),
anchor("center"),
color(rgb(0,0,0))
]);

add([
text("Game Over"),
pos(width() / 2, (height() / 2)- 200),
scale(2),
anchor("center"),
color(rgb(0,0,0))
]);

add([
text("Click to play again"),
pos(width() / 2, (height() / 2)+ 120 + 80),
scale(2),
anchor("center"),
color(rgb(0,0,0))
]);

// go back to game with space is pressed
onKeyPress("space", () => go("game"));
onClick(() => go("game"));

});

go("game");

Finally run npm run dev to run your game in your localhost or if the server is already started, just reload the tab.

and TADAAA… your Flying Jack game is ready.

Photo by Eilis Garvey on Unsplash

Follow me if you liked the content and want to learn something new every weekend.

--

--

Mithilesh Kr. Patel

Tech enthusiast and developer sharing my thoughts on software engineering, career growth, and staying productive. Let's level up together!