Your First PhaserJS Game

The Game World

Learn how to add, load, and animate game assets in PhaserJS, including background images, platforms, and character sprites, to bring your 2D platformer game to life.

Before we jump into building our game world, we need some assets—these are basically the building blocks of your game, like characters, backgrounds, platforms, and objects. They are visual or audio elements that make the game come to life. For example, a character running, platforms to jump on, or even a catchy background tune—all these are game assets. 🎮

In this chapter, we'll be working with visual assets. Since you don't need to hunt them down yourself, I've already added some assets to the project. You can find them in the public/assets folder. 📂

What Are Assets? 🎨

Assets are resources that your game uses, like images, sounds, and animations. Think of them as the "props" in your game that help tell the story or set the scene. Without assets, your game would just be an empty shell—no visuals, no action, and definitely no fun! 🎉

For our game, we're using assets from this awesome collection: Pixel Adventure. These cute, pixel-style graphics will be perfect for our 2D platformer! 🕹️

Loading Assets in PhaserJS 📦

In PhaserJS, before we can use any assets in the game world, we need to load them into memory. For that, PhaserJS provides a preload function, which is called automatically before a scene is loaded. It's like the game saying, "Let me get everything ready before we start." 🛠️

We will load our game assets in the preload method of the LoadingScene.js file. Here's the code:

    // background
    this.load.image("bg", "assets/bg.png")
 
    // spike
    this.load.image("spike", "assets/spike.png")
 
    // items
    this.load.spritesheet("apple", "assets/Items/Apple.png", {
        frameWidth: 32,
        frameHeight: 32
    })
    this.load.spritesheet("collected", "assets/Items/Collected.png", {
        frameWidth: 32,
        frameHeight: 32
    })
 
    // main character
    this.load.spritesheet("player_idle", "assets/character/idle.png", {
        frameWidth: 32,
        frameHeight: 32
    })
    this.load.spritesheet("player_hit", "assets/character/hit.png", {
        frameWidth: 32,
        frameHeight: 32
    })
    this.load.spritesheet("player_jump", "assets/character/jump.png", {
        frameWidth: 32,
        frameHeight: 32
    })
    this.load.spritesheet("player_run", "assets/character/run.png", {
        frameWidth: 32,
        frameHeight: 32
    })
 
    // platforms
    this.load.image("platform_brown", "assets/Platforms/Brown.png")
    this.load.image("platform_grey", "assets/Platforms/Grey.png")
 
    // falling platforms
    this.load.image("falling_platform_off", "assets/FallingPlatforms/Off.png")
    this.load.spritesheet("falling_platform_on", "assets/FallingPlatforms/On.png", {
        frameWidth: 32,
        frameHeight: 10
    })
 
    // Trampoline
    this.load.image("trampoline_idle", "assets/Trampoline/Idle.png")
    this.load.spritesheet("trampoline_jump", "assets/Trampoline/Jump.png", {
        frameWidth: 28,
        frameHeight: 28
    })

Explaining the Code 🧩

  1. this.load.image: This loads static images. For example, the background ("bg") and the platforms ("platform_brown", "platform_grey") are simple images that will be drawn in the game world.
  2. this.load.spritesheet: This loads a sprite sheet, which is an image divided into smaller frames. These are used for animations. For example, "player_run" is a sprite sheet where each frame of the character running is stored in one big image. Phaser cuts the image into smaller frames and then plays them in sequence to create an animation. We specify the frame dimensions (e.g., frameWidth: 32, frameHeight: 32).
  3. Platforms and Items: We load both static platforms (which don't move) and interactive items like apples or spikes. The trampoline also has two states: idle and when it's jumped on (you'll see this in action in the last chapter!). 🍎

Starting the Main Scene 🚀

Once the assets are loaded, we can move to the MainScene where the actual gameplay happens. To do this, we will switch scenes right after the assets are preloaded. This way, your game doesn't have to load assets every time you change levels or scenes. It's like prepacking everything in your backpack before starting a hiking trip—so you're ready to go without interruptions! 🏞️

To make this transition, we add the following line in the create function of LoadingScene.js:

    this.scene.start("MainScene");

What Does This Line Do? 🎭

  • this.scene.start("MainScene"): This tells Phaser to stop the current scene (which is just loading assets) and start the main game scene where all the action happens. Think of it like the curtain going up after everything has been set up on stage—now, it's showtime! 🎬

In short, this line ensures that after preloading the assets, the game smoothly transitions into the main gameplay, keeping things efficient and lag-free.

Adding Images and Sprites to the Scene 🎮

In this section, we're going to explore how to add images and sprites to the game scene and understand the difference between the two. Let's jump in!


Step 1: Adding an Image to the Scene 🖼️

Let's start with something basic: adding a background image. Add the following line of code to the create function in your MainScene.js file:

this.add.image(200, 300, "bg");

When you refresh your browser, you'll see that an image (our background tile) is now placed in the scene! 🎉

01

So, what does this line do? 🤔
  • this.add.image(200, 300, "bg");: This tells Phaser to add an image at coordinates x=200 and y=300. The third parameter, "bg", refers to the background image we loaded earlier in the preload method.

    This function is great for adding static images to the scene, like backgrounds, UI elements, etc.

Useful Image Functions 🔧

Phaser offers a few handy methods to manipulate images further:

  • setScale(x, y): It adjusts the size of the image. For example, scaling up an image 2 times can be done like this:

    this.add.image(200, 300, "bg").setScale(2);
  • setOrigin(x, y): Changes the point of origin of the image. By default, Phaser sets the origin to the center of the image (0.5, 0.5), but you can change it to the top-left corner (0, 0), for instance:

    this.add.image(200, 300, "bg").setOrigin(0, 0);

Step 2: Creating a Full Background 🌄

Instead of just placing a single background image, let's tile the background to cover the entire game canvas. Comment out the previous this.add.image line and add the following addBackground function:

addBackground() {
    for(let i = 0; i < 13; i++) {
        for(let j = 0; j < 13; j++) {
            this.add.image(i * 64, j * 64, "bg");
        }
    }
}

Don't forget to call this function inside the create method:

this.addBackground();
What's happening here? 🧐
  • We're using two for loops to create a grid of images that tile the background across the canvas.
  • i * 64 and j * 64: Each image is 64x64 pixels in size, so multiplying i and j by 64 ensures that every image is placed next to the previous one without gaps.
  • We assume the canvas is 800x800 pixels, so to cover the entire area, we need 13 rows and 13 columns of 64x64 images (800 ÷ 64 = 12.5, rounded up to 13).

Now, your game will have a beautiful tiled background. 🌄

01


Step 3: Adding the Main Character (Sprite) 🧑

It's time to introduce our main character! To do that, add this line after calling addBackground() in the create function:

this.player = this.add.sprite(100, 700, "player_idle");
this.player.setScale(2);
Explanation of the Code 🔍
  • this.add.sprite(100, 700, "player_idle"): Similar to adding an image, this line adds a sprite to the scene at coordinates (100, 700). A sprite is different from an image because it can have multiple frames, making it ideal for animations.
  • this.player.setScale(2): The character is a bit small by default, so we scale it up to twice its size.

01

Image vs. Sprite ⚖️

  • Images: Static, used for things like backgrounds, UI, etc.
  • Sprites: Dynamic and can hold animations. That's why we use a sprite for the character—so we can later add animations for walking, jumping, etc.

Step 4: Fixing the Blurred Sprite 🧐

If your character looks a bit blurry, don't worry! This happens because Phaser tries to smooth out the images by default. But since we're using pixel art, we want sharp edges. Let's fix that.

In the config.js file, add the following option inside your game configuration:

pixelArt: true,

Now the pixel art will look crisp and sharp, just as it should! 🔥

01


Step 5: Adding Animations to the Character 🎬

We've successfully added the main character, but he's just standing there, looking bored. Let's add some life by giving him animations!

Before we can use animations, we need to create them first. Add the following code to the loadingScene.js file inside the create function, right before the this.scene.start("MainScene"); line:

this.anims.create({
    key: "player_idle_anim",
    frames: this.anims.generateFrameNumbers("player_idle", { start: 0, end: 10 }),
    frameRate: 20,
    repeat: -1
});
 
this.anims.create({
    key: "player_hit_anim",
    frames: this.anims.generateFrameNumbers("player_hit", { start: 0, end: 6 }),
    frameRate: 20
});
 
this.anims.create({
    key: "player_jump_anim",
    frames: this.anims.generateFrameNumbers("player_jump", { start: 0, end: 0 })
});
 
this.anims.create({
    key: "player_run_anim",
    frames: this.anims.generateFrameNumbers("player_run", { start: 0, end: 11 }),
    frameRate: 20,
    repeat: -1
});
Breakdown of the Animation Code 🛠️
  • this.anims.create({...}): This function creates an animation.
  • key: This is the name of the animation. You'll use this name to play the animation later.
  • frames: This tells Phaser which frames of the sprite sheet to use for the animation. The generateFrameNumbers function is used to specify the start and end frame of the animation.
  • frameRate: This determines how fast the animation plays (frames per second).
  • repeat: -1: This makes the animation loop infinitely (useful for idle or running animations).

Step 6: Playing the Animation 🎥

Now that we've created the animations, let's play one. Add the following line in MainScene.js after you added the player:

this.player.anims.play("player_idle_anim", true);
What does this line do ❓
  • this.player.anims.play("player_idle_anim", true): This tells Phaser to play the idle animation we just created. The true parameter makes the animation loop continuously.

And voila! 🎉 Your character is now animated and comes to life with smooth idle animations.

05


Congratulations 🎉

You have successfully learned how to:

  • Add images and sprites to the scene.
  • Differentiate between static images and animated sprites.
  • Set up and play animations for your character.

Your game is getting more exciting with each step! Keep going, you are doing great! 🚀

Complete Code 📜

If you missed anything or made some accidental changes, here’s the complete code for reference! 💻🔧


import Phaser from "phaser";
import GameScene from "./scenes/gameScene";
import LoadingScene from "./scenes/loadingScene";
import MainScene from "./scenes/mainScene";
 
const config = {
    type: Phaser.AUTO,
    width: 800,
    height: 800,
    pixelArt: true, // To ensure the images don't blur out and retain their pixelated sharpness
    min: {
        width: 400,
        height: 400
    },
    scale: {
        mode: Phaser.Scale.FIT,
        autoCenter: Phaser.Scale.CENTER_BOTH // Centers the game in the middle of the screen
    },
    scene: [LoadingScene, MainScene, GameScene] // Our scenes, including the loading and game scenes
}
 
export default config;

Now you have everything! 🚀 Enjoy creating your awesome PhaserJS game!