You’re back! Coolsies. Let’s jump straight in, eh?

Bootstrapping Phaser

Whether you have a driver’s license or not, we’re all pretty familiar with how cars start. It won’t instantly turn itself on as soon as you sit down (I can’t speak for most automated cars, of course). You have to put the key in the ignition, and turn it. That sets off a chain of events, and presto-changeo the engine starts.

When we use a library like Phaser, the same thing applies. It can’t possibly know what we want it to do until we tell it. We call this bootstrapping, and it really just means that we’re going to put the key in the ignition, and turn it.

Let’s see how that looks.

In VSCode, open invaders.js. It should be empty. Let’s type:

// FIRST: Phaser configuration.
var config = {
    type: Phaser.AUTO,
    width: 800,
    height: 600,
    physics: {
        default: 'arcade'
    }
};

// SECOND: Jump-start Phaser with our configuration.
var game = new Phaser.Game( config );

We’ll go line-by-line here, just to see what’s happening.

var config = {

Alright, we’re creating an object variable called config. Easy enough. What’s next?

    type: Phaser.AUTO,

Phaser supports two different rendering — as you’ll recall from part 1, rendering just means “drawing on the screen” — types: “canvas” and “WebGL”. Feel free to click those links if you want to learn more about those. I won’t delve too much into them right now. Just know that these are each useful for different things in different ways.

When we’re not really sure which to use we can tell Phaser to figure it out for us by using a type of Phaser.AUTO.

Moving on to:

    width: 800,
    height: 600,

The width and height guys tell Phaser how big it should be on the page. This represents the number of pixels in each dimension. In this case, we want Phaser to use an area that’s 800 pixels wide and 600 pixels tall.

Now we come to an interesting little object called physics.

    physics: {
        default: 'arcade'
    }

Phaser supports all sorts of physics. Y’know? Things like gravity, elasticity (also known as bounciness), etc. You can dig really deep and fine-tune these things inside Phaser, but when you just want to get going Phaser also offers some predefined physics settings. We call these defaults, and by setting default: 'arcade' we’re telling Phaser to use the predefined physics settings that it calls “arcade”.

That brings us to:

var game = new Phaser.Game( config );

We’re clearly creating a new variable called game, but what’s the rest of it? The new keyword is exactly what it sounds like, which is to say that we’re creating a brand-new… something. We already have Phaser, so why do we need to create a new Phaser-thing?

Because Phaser is big. In terms of what it enables us to do it has a lot of stuff in it. Think of Phaser as a big store like Target or Wal-Mart. There’s departments for groceries, clothes, electronics, household goods. Lots of stuff, right? When was the last time you heard, “I’m going to pick up a Target from Target”? Never, right? That’d be weird. No, it’s more something like, “I’m going to pick up some groceries from Target.”

Let’s look at some pseudo-code (which means that it just looks like code to help us better visualize a concept). We don’t want to put this into our file.

var lettuce = Target.Groceries;

See that . right in the middle? We call that dot notation, and it’s a way for us to separate big things (Target) into the smaller things inside (Groceries). So we could have something like:

var Target = {
    Groceries: {
        Produce: {
            Lettuce: [
                {
                    type: 'butterhead',
                    name: 'Butterhead Lettuce'
                },
                {
                    type: 'celtuce',
                    name: 'Celtuce Lettuce'
                }
            ],
            Cereal: [
                // More stuff here.
            ],
            // More stuff here.
        },
        // More stuff here.
    },
    Electronics: {
        // Stuff
    }
};

When you put it all together — Target.Groceries.Produce.Lettuce — you get what we call a namespace. You don’t have to remember that right now, but as we progress it’ll be super handy to know how to use namespaces to look up how to use different pieces of things.

Back to our Target analogy. We want lettuce from the store, but there’s lots of different types. Also, each type of lettuce has lots of individual packages. Usually you only want a single package of lettuce, unless you’re a rabbit. In developer-speak, when we say that we want one of something, we say that we want an instance of it.

How do we get a single instance of Phaser.Game? We use new. That tells Phaser that I want a single unique copy of Phaser.Game that can’t be used anywhere else. It’s only mine.

It’s okay if you’re overwhelmed with that. It can be a difficult concept to grasp, but no worries. You’ll pick it up as we go along!

Here’s how it should look in invaders.js right now:

Configuring and instantiating Phaser
I wonder what happens if we run this?

Yeah, let’s run it and see what happens.

Go ahead and open up your Integrated Terminal (I think I’ll just call it Terminal from now on), and type:

npm start

Running our Phaser game for the first time
This is going to be so cool!

Press Enter. Aaaand…

Not what we expected
I don't think it's supposed to do that.

It’s blank. Just an empty 800 pixels wide by 600 pixels tall black box. Thought there’d be more fireworks? Don’t sell yourself short! We can see that Phaser used our configuration, and created a playing area exactly the size that we told it to. Which means you’ve:

  • Successfully setup the project.
  • Successfully pulled in and used the Phaser library.
  • Successfully configured and created an instance of Phaser’s Game object.
  • Launched it inside a web browser, and can see that it’s working.

You’ve already done a lot! But we can do more. And we will. Right now.

Events and Hooks

Once Phaser gets going it stays going — unless you break something in your code — which is why it’s called a game engine. In fact, think of it like a train stopping at stations to pick up new passengers. At each station, special types of passengers board the train. In programming terms, these are called events.

In Phaser, there are hundreds of events happening many times every second. In order to ensure a smooth-running train schedule, Phaser only allows us access to certain important events, and it’s up to us to use them. The Phaser train is going to pass through those stations whether there’s any passengers there or not.

If we want to board the train at a particular station — tap into one of those events when Phaser fires it — we have to write something called a hook. When the Phaser train passes one of the stations we want to use, it doesn’t stop for us. We stick our hand out, and it grabs whatever we push at it before moving on.

For our game we need to write hooks for only three events: preload, create, and update.

The preload Event

This is one of the first stations that the Phaser train passes through, and it gives us a chance to get our graphical assets ready. These are things like images and sprites, which we’ll talk about in a bit. This is the only event where Phaser is accepting things like this, so we need to be ready for it.

The create Event

Have you ever been to Grand Central Station in New York, or Union Station in Chicago? Those aren’t little dusty train stations out in the middle of nowhere. They’re big and busy, and they’re used a lot. This is the event where we’ll do a lot of stuff also, mainly setting up the different pieces of the game. Like the score board, the player’s ship, and the alien invaders.

The update Event

Phaser doesn’t even slow down for this station. It flies right on through, about 60 times every second. This is where we’re going to check whether the player is pressing the keyboard arrows to move, and making the background scroll. We don’t want to do a lot here, just because it happens so often.

Stubbing Out the Hooks

When we create only the basic structure of functions and objects, we like to say that we’re stubbing them out. Kinda like a ticket stub to a baseball game. It’s not the full ticket, but it’s got just enough information that you know what it is.

Let’s do it! I’m going to include a line of code that you’ve previously typed, just so you know where I expect you to put your next code. Cool? Alright!

// SECOND: Jump-start Phaser with our configuration.
var game = new Phaser.Game( config );

// HOOK, PART 1: The preload hook.
function handlePreload() {

}

// HOOK, PART 2: The create hook.
function handleCreate() {

}

// HOOK, PART 3: The update hook.
function handleUpdate() {

}

In VSCode:

The event hooks stubbed out
Our event hooks are stubby!

These functions are useless right now, so let’s make sure that Phaser picks them up from the right station at the right time. Head back up to your configuration object at the top of the file, so we can hook them up.

// FIRST: Phaser configuration.
var config = {
    type: Phaser.AUTO,
    width: 800,
    height: 600,
    physics: {
        default: 'arcade'
    },
    scene: {
        preload: handlePreload,
        create: handleCreate,
        update: handleUpdate
    }
};

We added a new property to our config object: scene. A scene in Phaser is kinda like a scene in a movie. In Spider-Man: Homecoming, Peter Parker talks to Tony Stark in the car. Then the screen goes to black for a split second, and suddenly Peter Park is on the train going to school! A movie is made up of many scenes, and so can your game. You can make a game almost as big as you want with Phaser, and the way you split up a big game is with multiple scenes.

We only need one scene, which is why the value of scene is a very simple object. The only properties that our scene object has are the three events that we want to hook into. Each of those properties has a value that corresponds to one of the functions we just wrote.

That’s it! That’s all we need to do to make sure that our hooks are connected properly! Make sure you save your invaders.js file with our new code. Your browser will update, but since we still haven’t given Phaser anything to show, it’ll remain blank.

Let’s fix that.

Images, Sprites, and Everything Nice

I’ve taken the liberty of creating our graphics for this project, so you don’t have to. Once we’re done with this project, you can feel free to change those images as much as you like. Go nuts! Make the player’s ship a hamburger!

For each of these, right-click the link and then click “Save As…”, and choose the folder that has the rest of your project files in it.

  • bullet.png is a simple image of the bullet that will fire from the player’s ship.
  • enemy-bullet.png is another image of the bullet that the alien invaders will fire from their ships at the player.
  • explode.png is an image sprite, and contains the frames of animation to render an explosion. If you open this image in a photo viewer, you can see that the frames are ordered from left-to-right.
  • invader.png is a simple image of an alien invader’s ship.
  • invader50x60x10.png is another image sprite, and contains the frames of animation to render each alien invader’s “hover” movement. The name is important 50x60x10 refers to the width (50) and height (60) of each frame, and how many frames are in the animation (10).
  • player.png is a simple image of the player’s ship.
  • starfield.png is our background image that we’ll be tiling and animating ourselves from the handleUpdate function.

Just in case you could use some visual help:

  1. Right-click the link in the list.

    Right-clicking the link
    Right-clicking the first link. Repeat this process for the others.

  2. In the “Save As” file window, make sure you’re in the right spot. The filename shouldn’t need to be changed, and should match what’s in the list. Then click ”Save“.

    Save As
    Make sure you're saving to your project folder!

  3. Repeat for the other images. You should have a total of 7 when you’re done.

  4. And here’s how it should look in VSCode:

    Final result in VSCode
    The final result in VSCode.

How about we actually use one of these images!

Creating the Starfield Background

We’re going to create the appearance of moving through space, just like the old games used to do. Head back into VSCode, and go to your invaders.js file.

And since I know you’re up for it, we’re going to do this next part without any training wheels (but I like you, so I’ll still include some screenshots at the end).

Using preload to make Phaser Aware of Our Graphics

Inside of our handlePreload function is where we’re going to begin. Let’s update that function to look like this:

// HOOK, PART 1: The preload hook.
function handlePreload() {

    // Preload our "sky".
    this.load.image( 'starfield', 'starfield.png' );
}

So this line introduces another new concept, which is the keyword this. We won’t go too deep into this topic right now, but let’s go back to the train analogy. handlePreload is connected to Phaser’s preload event. When the Phaser train passes through the preload station, everything inside handlePreload is now happening inside the Phaser train. The conductor reached down, grabbed what we were trying to put onto the train, and kept moving. So as long as we’re inside handlePreload, this means Phaser train.

Phaser has a special helper object called load. It’s a super handy helper that exists solely to help us get things ready to use inside the game. One thing that helper object does is load images.

The load.image function takes two parameters.

  1. A unique name — which must be a string — that we give it, so that we can refer to it later. As we add graphic assets to Phaser, it keeps track of them using the special name that we give each one.

  2. The file path to the asset, meaning… from where this file lives, which folders does Phaser need to look at to find the file? Since all of our images live in the same directory as invaders.js we can just give it the plain old filename, without any folders. We’ll talk more about file paths in another project.

Make sure you save before you continue!

Creating a Variable to Hold Our Background Image

Using preload to load the image isn’t all we need to do. We also need to add it to our scene, and to do that we have to create a variable to store it. That way, we can move it around from inside the update hook.

Just beneath your game variable, type this:

// SECOND: Jump-start Phaser with our configuration.
var game = new Phaser.Game( config );

// This is our starfield background image.
var starfield;

We just declared an empty variable named starfield. No big deal, right? It’s time for a curveball!

Creating and Placing the Starfield Tile Sprite

Now we’re going to finally use our imported asset — along with our valueless variable — and put something on the screen that we can see!

Inside our handleCreate function:

function handleCreate() {

    // Set starfield's value to be a tile sprite, and make sure it's scaled properly.
    starfield = this.add.tileSprite( 0, 0, 2048, 2048, 'starfield' );
    starfield.setScale( 1 );
}

There’s that crazy this keyword again. Remember, if we’re inside a function called from one of those three events (preload, create, and update), we’re on the Phaser train, which means this refers to our Phaser scene.

What’s a tileSprite? In short, it’s an image that we intend to use as a repeatable pattern. We want the moving starfield to never run out, right? Space is endless, so we need it to appear endless. Since we can’t make a neverending image, we create smaller images that can be “tiled”. They can be put edge to edge, and it looks seamless.

add.tileSprite takes four parameters, and the first two are special. These are xy coordinates, and they’re numbers.

0, 0, means “place the top-left corner of my image 0 pixels from the left and 0 pixels from the top of my scene.”

Imagine a grid like this:

x   x   x   x   x   x   x   x   x   x   x   x
x   x   x   x   x   x   x   x   x   x   x   x
x   x   x   x   x   x   x   x   x   x   x   x
x   x   x   x   x   x   x   x   x   x   x   x
x   x   x   x   x   x   x   x   x   x   x   x

If I wanted to place an image that’s 6 pixels wide and 4 pixels tall at the xy coordinates of 6, 2, then the top-left corner of the image would start right here:

x   x   x   x   x   x   x   x   x   x   x   x
x   x   x   x   x   x   x   x   x   x   x   x
x   x   x   x   x   x   O   O   O   O   O   O
x   x   x   x   x   x   O   O   O   O   O   O
x   x   x   x   x   x   O   O   O   O   O   O

We want to start it at 0,0 because we want it to cover the whole screen.

Then we see two more numbers: 2048, 2048. This is the width and height of the image as we want it to be displayed. The actual image is only 1024 pixels wide by 1024 pixels tall, but Phaser assumes that a tileMap will have to work in all four directions. We only need it to work in two: up and down. So we double the size of the image to get around Phaser trying to treat it like a quarter-sized tileSprite.

That sounds complicated, I know. That’s okay. It’s a lot to remember. You don’t have to know the whole world in a day!

And remember up top, when we used preload to import our starfield image? I mentioned that we had to give each one a unique name. The last parameter is exactly the reason why. We need to tell Phaser to fill that tileSprite with a preloaded image, so we give it the unique name that we gave during preload.

Finally, we’re calling starfield.setScale( 1 );. This is what Phaser refers to as the “scale factor” of the object. In the event that Phaser would need to zoom in or out, this is the scale that it would use as a multipler to set a new size. Fortunately, for this project, we don’t have to worry about scaling, so we set the value to 1 (it won’t scale).

Alright, since I like you so much, let’s do a little code review to see what our invaders.js file should look like now.

After adding our starfield
We've added a starfield! Right?

Make sure you save before you continue!

And when you save, your browser should automatically update! If all went well — and it should, since I showed you the code, silly goose — your browser should look like this:

We have a starfield!
We've added a starfield!

Moving the Starfield Background

Alright, we’re almost done with this post. Home stretch. We’re going to continuously move the background to give it the appearance of traveling.

This is going to be difficult, right? Nay. You need add only one line of code to your handleUpdate function, and here it is:

function handleUpdate() {
    // Scroll our starfield background.
    starfield.tilePositionY += 2;
}

THAT’S IT! That’s all you need to move it.

Remember, the update event fires many, many, many times every second. This one line of code basically says, “Set starfield’s y coordinate after adding 2 to it.” So if starfield.tilePositionY is currently set to 5, this line of code will make it 7.

You may be wondering about the +=. It’s a bit of a shortcut. If we wanted to do it the hard way, we could write:

starfield.tilePositionY = starfield.tilePositionY + 2;

Since we’re setting a variable’s value to a simple increment of itself, we can use the shorthand += to save ourselves a little extra typing.

Make sure you save your file before continuing!

Now go check out your handiwork in the browser. You should see a nice scrolling starfield back there. In the next post, we’re going to add our player ship and figure out how to control it with the keyboard!

You can find the source code for this series at GitHub.