Teach kids to code by making games

  • Post author:
  • Post category:Beginner
Teach your child programming while making games!

Introduce your kid to the joys of Javascript web programming by making a video game together (live game link, and code link). This tutorial teaches you how to use Phaser, a popular Javascript game engine, with Glitch, a common platform for sharing Javascript applications. No prior programming experience necessary, no need to install any applications.

This tutorial is a stream-lined version of the the Phaser tutorial, tailored for parents and kids to do together. It’s the first of three lessons in our Platformer course.

Also, if you ever get stuck or have any questions, feel free to reach me on Twitter (link).

Starting off with Glitch

First, we’ll start with a basic Glitch project, which contains a simple index.html that loads the Phaser library and calls an empty main.js . Glitch is a great way to code and run our javascript game in the browser. Click this Glitch link to open the project in a new tab.

Next, you’ll need to click the Remix to Edit button to make a copy of the project so you can edit it:

Click the Remix to Edit button

Next, we’ll tell Glitch to show our app in a new window (instead of next to our code). That way when we make changes to our Javascript code, it’ll update in our app. We can do this by clicking the Show button on the top of our Glitch project, and then clicking In a New Window:

Click Show, then select In a New Window.

As a final setup, I like to open 2 browser windows, with this post open on the left, and my code/app in the right window, like this:

We can scroll along the post while coding on the right.

Configuring our game

First, we’ll configure and create the Phaser game. Write the following code into main.js :

import Phaser from '/phaser.js';
// Create a Phaser config
var config = {
type: Phaser.AUTO,
width: 800,
height: 600,
scene: {
preload: preload,
create: create,
update: update,
},
};
// Create a game from the config
var game = new Phaser.Game(config);
function preload() {
}
function create() {
}
function update() {
}

This code creates a game of size 800×600 pixels and adds hooks that will be called during different parts of your game. When your game needs to load images, it’ll call the preload() function. When your game adds sprites and other objects, it’ll call create() . When your game updates sprites and other objects, it’ll call update() .

Click the refresh button and you should see a black window representing our game. If not, make sure you click “Show” and “Next to the Code” on the top-left.

Adding images to our game

Now we’ll add the sky, stars, bomb and player images to the game.

First let’s load some images! Download the images and add each one into the assets folder, below. This will allow your Glitch project to refer to those images:

Drag images into the assets folder

When you click on an image you’ve loaded, you should see a preview of the image as well as its url. Take note of that url since you’ll need it later on.

Note the url, you’ll need it later in your code

Now we can load these images into our game by adding the following into the preload function:

function preload() {
this.load.image(
'sky',
'https://cdn.glitch.com/80943e04-3457-4c26-8e97-8948bc3c0dbe%2Fsky.png?v=1628448347307'
);
this.load.image(
'ground',
'https://cdn.glitch.com/80943e04-3457-4c26-8e97-8948bc3c0dbe%2Fplatform.png?v=1628449301558'
);
this.load.image(
'star',
'https://cdn.glitch.com/80943e04-3457-4c26-8e97-8948bc3c0dbe%2Fstar.png?v=1628449307035'
);
this.load.image(
'bomb',
'https://cdn.glitch.com/80943e04-3457-4c26-8e97-8948bc3c0dbe%2Fbomb.png?v=1628449295044'
);
this.load.spritesheet(
'dude',
'https://cdn.glitch.com/80943e04-3457-4c26-8e97-8948bc3c0dbe%2Fdude.png?v=1628449297658',
{ frameWidth: 32, frameHeight: 48 }
);
}

This code tells the Phaser game engine to load those images from those URLs into memory, although it’s not visible (yet) in the game. The first argument is the name of the image (like “sky”). The second argument tells Phaser where to load the image. Note your URLs will be specific to your project! Later, we’ll use the image’s name when we add it to the game.

Note the last image is loaded as a “sprite sheet”, which is like multiple animation frames of a cartoon. We’ll see later on how we can use these frames to make the player appear to “walk” or “turn”.

Building the world

Once we’ve loaded these images, let’s build the game world, starting with adding the sky, by adding the following code in the create function:

function create() {
// Adds the sky image to our game, centered at 400, 300
this.add.image(400, 300, 'sky');
}

This will tell Phaser to add the image named “sky” and position it at (400, 300), which is in the middle of the game (remember that the game is 800×600 pixels). If you run your game now, it should show a sky!

Next, let’s add some platforms into our game, but before we do that we’ll need to add a physics engine to our game. The physics engine enables our game to simulate gravity, collisions with other objects, etc. Let’s add the physics attribute into the config :

var config = {
type: Phaser.AUTO,
width: 800,
height: 600,
// Add this code below until you reach the "stop" comment
physics: {
default: 'arcade',
arcade: {
gravity: { y: 300 }
},
},
// stop
scene: {
preload: preload,
create: create,
update: update,
},
};

Now we can use the physics engine to create a static group and add some platforms to it. Static objects aren’t affected by gravity or other forces (like collisions by other objects). Dynamic objects, on the other hand, bounce around and are affected by other objects.

Let’s add some platforms into a group of static objects in the create function:

function create() {
this.add.image(400, 300, 'sky');
// Add this code below until the "stop" comment
var platforms = this.physics.add.staticGroup();
platforms
.create(400, 568, 'ground')
.setScale(2)
.refreshBody();
platforms.create(600, 400, 'ground');
platforms.create(50, 250, 'ground');
platforms.create(750, 220, 'ground');
// stop
}

Line 5 creates a platforms variable that we can add to. The first platform is a stretched out ground image, which is what the .setScale(2) call does. The other lines add the ground image to various positions in the game. Let’s reload our game and see what it looks like!

Adding platforms to our game!

Adding the player

Now that we’ve built the game world, let’s add our player. First, we’ll create a variable called player , right at the top of main.js:

import Phaser from '/phaser.js';
// Add the following code until the "stop" comment
var player;
// stop
var config = {

Next, in the create() function we’ll add the player to our game and configure it.

function create() {
this.add.image(400, 300, 'sky');
var platforms = this.physics.add.staticGroup();
platforms
.create(400, 568, 'ground')
.setScale(2)
.refreshBody();
platforms.create(600, 400, 'ground');
platforms.create(50, 250, 'ground');
platforms.create(750, 220, 'ground');
// add this code below until the "stop" comment
player = this.physics.add.sprite(100, 450, 'dude');
player.setBounce(0.2);
player.setCollideWorldBounds(true);
this.anims.create({
key: 'left',
frames: this.anims.generateFrameNumbers('dude', { start: 0, end: 3 }),
frameRate: 10,
repeat: -1,
});
this.anims.create({
key: 'turn',
frames: [{ key: 'dude', frame: 4 }],
frameRate: 20,
});
this.anims.create({
key: 'right',
frames: this.anims.generateFrameNumbers('dude', { start: 5, end: 8 }),
frameRate: 10,
repeat: -1,
});
// stop
}

While adding the player, we also setBounce(0.2), which controls how much the player bounces when they collide with something, and we also set setCollideWorldBounds(true), which says the player will collide with the boundary of the world (and not fall out of it).

We also created a few animations, called leftright, and turn. These animations cycle through the frames in the dude sprite sheet we loaded earlier:

The ‘dude’ sprite sheet

The left animation cycles through sprites 0 and 3, which as you can see, makes the player appear to walk to the left. Similarly, the right animation cycles through frames 5–8, which makes the player appear to walk right.

If we load our game now, we’ll see our player, but he falls through the ground and onto the edge of the game!

Our player falls through the ground, but stays in the game.

That’s because we haven’t told our game that the player must collide with the platforms as well. So let’s add that:

function create() {
this.add.image(400, 300, 'sky');
var platforms = this.physics.add.staticGroup();
platforms
.create(400, 568, 'ground')
.setScale(2)
.refreshBody();
platforms.create(600, 400, 'ground');
platforms.create(50, 250, 'ground');
platforms.create(750, 220, 'ground');
player = this.physics.add.sprite(100, 450, 'dude');
player.setBounce(0.2);
player.setCollideWorldBounds(true);
this.anims.create({
key: 'left',
frames: this.anims.generateFrameNumbers('dude', { start: 0, end: 3 }),
frameRate: 10,
repeat: -1,
});
this.anims.create({
key: 'turn',
frames: [{ key: 'dude', frame: 4 }],
frameRate: 20,
});
this.anims.create({
key: 'right',
frames: this.anims.generateFrameNumbers('dude', { start: 5, end: 8 }),
frameRate: 10,
repeat: -1,
});
// Add the code below until the "stop" comment
this.physics.add.collider(player, platforms);
// stop
}

If you run your game now, your player will now stand on the platform. Nice!!

Adding player collisions to make them stand on the platforms

Controlling our player

Now that we’ve added a player to our world, let’s control it by using the arrow keys. There are two things we’ll do:

  1. create a cursors variable, which tracks our keyboard “arrow” keys
  2. check when the arrow keys are pressed down and move our player appropriately

So first, let’s declare the cursors variable:

import Phaser from '/phaser.js';
var player;
// add the next line to declare the cursors variable
var cursors;
var config = {

Then, at the bottom of the create() function we’ll define cursors:

function create() {
this.add.image(400, 300, 'sky');
var platforms = this.physics.add.staticGroup();
platforms
.create(400, 568, 'ground')
.setScale(2)
.refreshBody();
platforms.create(600, 400, 'ground');
platforms.create(50, 250, 'ground');
platforms.create(750, 220, 'ground');
player = this.physics.add.sprite(100, 450, 'dude');
player.setBounce(0.2);
player.setCollideWorldBounds(true);
this.anims.create({
key: 'left',
frames: this.anims.generateFrameNumbers('dude', { start: 0, end: 3 }),
frameRate: 10,
repeat: -1,
});
this.anims.create({
key: 'turn',
frames: [{ key: 'dude', frame: 4 }],
frameRate: 20,
});
this.anims.create({
key: 'right',
frames: this.anims.generateFrameNumbers('dude', { start: 5, end: 8 }),
frameRate: 10,
repeat: -1,
});
this.physics.add.collider(player, platforms);
// Add this line of code below
cursors = this.input.keyboard.createCursorKeys();
}

The cursors variable allows us to access the arrow keys. We’ll check if the left, right, or up keys are pressed and move our player. Let’s change our update() function with the following code:

function update() {
if (cursors.left.isDown) {
player.setVelocityX(-160);
player.anims.play('left', true);
} else if (cursors.right.isDown) {
player.setVelocityX(160);
player.anims.play('right', true);
} else {
player.setVelocityX(0);
player.anims.play('turn');
}
if (cursors.up.isDown && player.body.touching.down) {
player.setVelocityY(-310);
}
}

In lines 2–4, we check if the left arrow key is pressed down. If so, we’ll “move” the player 160 pixels to the left, while also playing the leftwalking animation.

Similarly, for lines 5–7, we check if the right arrow key is pressed down, and move the player to the right.

In lines 9–10, if no key is pressed, then just set the player’s velocity to 0 (to keep them from “floating”) and play the turn animation.

In lines 12–13, we check if the up key is pressed down, and also if the player is touching a platform (we don’t want the player to jump from mid-air!).

Let’s run the program and try it out!

Awesome! We can control our player!

Adding stars to collect

Now that we can move around in our world, let’s add some stars to collect.

First, we’ll declare a stars variable in the main.js file:

var player;
var cursors;
// Add the following line of code until the "stop" comment
var stars;
// stop
var config = {

Next we’ll add stars in random locations in our game. At the bottom of the create() function, add:

function create() {
this.add.image(400, 300, 'sky');
var platforms = this.physics.add.staticGroup();
platforms
.create(400, 568, 'ground')
.setScale(2)
.refreshBody();
platforms.create(600, 400, 'ground');
platforms.create(50, 250, 'ground');
platforms.create(750, 220, 'ground');
player = this.physics.add.sprite(100, 450, 'dude');
player.setBounce(0.2);
player.setCollideWorldBounds(true);
this.anims.create({
key: 'left',
frames: this.anims.generateFrameNumbers('dude', { start: 0, end: 3 }),
frameRate: 10,
repeat: -1,
});
this.anims.create({
key: 'turn',
frames: [{ key: 'dude', frame: 4 }],
frameRate: 20,
});
this.anims.create({
key: 'right',
frames: this.anims.generateFrameNumbers('dude', { start: 5, end: 8 }),
frameRate: 10,
repeat: -1,
});
this.physics.add.collider(player, platforms);
cursors = this.input.keyboard.createCursorKeys();
// Add the following code until the "stop" comment
stars = this.physics.add.group({
key: 'star',
repeat: 11,
setXY: { x: 12, y: 0, stepX: 70 },
});
stars.children.iterate(function(child) {
child.setBounceY(Phaser.Math.FloatBetween(0.4, 0.8));
});
this.physics.add.collider(stars, platforms);
// stop
}

Lines 44–48 adds 11 stars to our game. We add it to a physics group so the stars are affected by gravity and interact with our game objects. The key: 'star' code refers to the star image we loaded earlier. Line 47 tells our program to add stars starting from 12 pixels to the left, and 0 from the top. Each time we add a star, step to the right by 70 pixels.

In lines 50–52 we loop through each star and set its bouncy-ness to a fraction between 0.4 and 0.8.

Finally, on line 54 we make sure our stars collide with the platforms (and don’t fall through the game!). If you refresh your game now, you should see bouncing stars!

Notice how the stars bounce to different heights

If you move your player through a star, you’ll notice nothing happens. This is because we haven’t told our game that our player can collide with stars, and what to do when it does. Let’s add that logic now.

When our player touches a star, we want to add to a running score. So we’ll first we’ll need to add a score to the screen. Let’s do that by adding two new variables:

var player;
var cursors;
var stars;
// Add the following code until the "stop" comment
var score = 0;
var scoreText;
// stop
var config = {

Next, we’ll define and add the scoreText to our game at the bottom of the create() function:

function create() {
this.add.image(400, 300, 'sky');
var platforms = this.physics.add.staticGroup();
platforms
.create(400, 568, 'ground')
.setScale(2)
.refreshBody();
platforms.create(600, 400, 'ground');
platforms.create(50, 250, 'ground');
platforms.create(750, 220, 'ground');
player = this.physics.add.sprite(100, 450, 'dude');
player.setBounce(0.2);
player.setCollideWorldBounds(true);
this.anims.create({
key: 'left',
frames: this.anims.generateFrameNumbers('dude', { start: 0, end: 3 }),
frameRate: 10,
repeat: -1,
});
this.anims.create({
key: 'turn',
frames: [{ key: 'dude', frame: 4 }],
frameRate: 20,
});
this.anims.create({
key: 'right',
frames: this.anims.generateFrameNumbers('dude', { start: 5, end: 8 }),
frameRate: 10,
repeat: -1,
});
this.physics.add.collider(player, platforms);
cursors = this.input.keyboard.createCursorKeys();
stars = this.physics.add.group({
key: 'star',
repeat: 11,
setXY: { x: 12, y: 0, stepX: 70 },
});
stars.children.iterate(function(child) {
child.setBounceY(Phaser.Math.FloatBetween(0.4, 0.8));
});
this.physics.add.collider(stars, platforms);
// Add the following code until the "stop" comment
scoreText = this.add.text(16, 16, 'score: ' + score, {
fontSize: '32px',
fill: '#000',
});
// stop
}

Lines 56–59 add text at position (16, 16). The text string is score: 0 since score is initially set to 0.

Now let’s add the code that updates the score when our player collides with a star. Let’s first add a new function collectStar(player, star) which we’ll call when a player overlaps with a star:

function collectStar(player, star) {
star.disableBody(true, true);
score += 10;
scoreText.setText('Score: ' + score);
}

Line 2 disables the star from the game. Lines 4–5 increment the score and updates the score text in the game.

Now, let’s have our game call this function when the player and a star overlap:

function create() {
// (I've skipped showing all the code we wrote before)
// Just add the line of code below
this.physics.add.overlap(player, stars, collectStar);
}

Line 5 tells our physics engine that if our player and an star overlap in the game, the call the collectStar function we wrote. Let’s run the game and test it out!

Adding bombs

Ok almost done. What’s a game if it doesn’t have a challenge? Let’s add some bombs that bounce around if you collect all the stars. What happens if you touch a bomb? BOOM. Game over!

First, let’s add a bombs variable and assign it to a physics group. Remember that a physics group lets us collide it with other objects in our game:

var player;
var cursors;
var stars;
var score = 0;
var scoreText;
// Add the following line of code
var bombs;

At the bottom of your create() function, add create the bombs:

function create() {
// (I've skipped showing all the code we wrote before)
bombs = this.physics.add.group();
this.physics.add.collider(player, bombs, hitBomb, null, this);
this.physics.add.collider(bombs, platforms);
}

In lines 4–6, at the bottom of the create()function we add physics group. Then we tell our game that our player can collide with bombs. When it does, then call the hitBomb function, which we’ll define below. Finally, in line 6 we specify that the bomb can bounce off the platforms.

Now, let’s add the hitBomb function, which describes what happens when a player touches a bomb:

function hitBomb(player, bomb) {
this.physics.pause();
player.setTint(0xff0000);
player.anims.play('turn');
this.add.text(200, 150, 'Game Over!', { fontSize: '64px', fill: '#000' });
}

Line 2 says to pause all physics, so all objects stop moving in the game. Lines 4–5 tints our player red, and resets the animation. Line 7 shows the text “Game Over” in big bold font, in the middle of the screen.

Now that’ve added code for when a player hits a bomb, when does the bomb show up? Well, let’s add the following code in the collectStar(player, star) function:

function collectStar(player, star) {
star.disableBody(true, true);
score += 10;
scoreText.setText('Score: ' + score);
// Add the following code until the "stop" comment
if (stars.countActive(true) === 0) {
stars.children.iterate(function(child) {
child.enableBody(true, child.x, 0, true, true);
});
var x =
player.x < 400
? Phaser.Math.Between(400, 800)
: Phaser.Math.Between(0, 400);
var bomb = bombs.create(x, 16, 'bomb');
bomb.setBounce(1);
bomb.setCollideWorldBounds(true);
bomb.setVelocity(Phaser.Math.Between(-200, 200), 20);
bomb.allowGravity = false;
}
// stop
}

Line 8 is an “if-statement”. It says that if there are no more active stars, thendo the following code. Lines 9–10 loop through all the stars, and reenables them. This means the stars will reappear.

Next, in lines 13–16, we define a variable x using a “ternary” operator. This simply says, “check if the player is to the left 400 pixels”. If the player is indeed to the left, then x will be a random number between 400–800. Else, x will be a random number between 0–400. Basically, we want to create a bomb on the opposite side of the screen from the player.

Finally, lines 18–22 create the bomb, set how bouncy it is, make sure the bomb collides the world boundaries, set a random velocity, and disallow gravity to affect it.

Now let’s run our game and test it out!

Conclusion

Congratulations on writing your very first Javascript game! You are well on your way to learning Javascript and writing fun games too!

If you got stuck or have any questions, feel free contact us and we’ll be sure to get back to you!