Phaser Coding Tips 6
Phaser Coding Tips is a free weekly email - subscribe here.
Welcome!
Back in the late 80s I was utterly captivated by an Usborne range of programming books, one of which was Computer Battlegames (for the ZX Spectrum, et all).
The front cover and illustrations within this book promised great things! In reality only one game in the entire book even had any graphics (everything else was text mode). But that didn't stop it firing my imagination. For this weeks coding tip I've taken one of the games from the book and bought it into Phaser.
Get the source
I'm only going to highlight the most important parts of the code here. So please always look at the source first. If you've questions about something I didn't cover then ask on the forum. Run / Edit the code on jsbin or codepen Clone the phaser-coding-tips git repo.
Shootout
"You are standing back to back. You take 10 paces, turn and reach for your guns. How quick are you? Can you shoot first?" That was the blurb from the original game in the book. It accompanied 15 lines of code and a lavish spaghetti western style illustration. For our rendition Ilija has given it a pixel art look instead.
The game consists of just 1 image, which we'll change the texture of, some text and a bunch of timers to handle the shooting.
Structure
If you look at the source you'll notice that we're using a slightly different structure this week. This is because we've a few assets to load (audio mostly) and we want a Preloading screen to display that. To do this we create 3 States: Boot, Preloader and Game within a Shootout
object. Boot handles setting up some input values and then loading our preloader assets (a small logo and a preloader bar). Once we've got those the game proceeds to the Preloader state. In here it's business as usual. We display a sprite, a preloader bar and load the assets. The only part that may be new to you is the update
loop waiting for the audio to decode before carrying on. We're using mp3 files which have a latency involved not only in loading but also in decoding before they can be played. As we use them in the game we don't want the game to start until they're ready to play. So we simply check their decoded status in our update loop:
this.cache.isSoundDecoded('casing')
Once they are all ready we proceed to the Game state.
The Game Flow
The basic flow of the game is this: * There is a "10" paces count down timer * After this we pick a random time before the game displays 'Draw' * At this point we pick a random time that the Cowboy will shoot in * If you shoot first, you win. * If he shoots first, you lose. After the cowboys have 'paced away' the delay time before they are expected to draw their guns is defined:
var delay = this.rnd.between(500, 3000);
Once they are allowed to draw, the speed at which the cowboy will shoot you is set. This is done using two properties defined in the Game constructor:
this.reactionTimeMin = 100;
this.reactionTimeMax = 500;
So it will pick a random time between 100ms and 500ms. If your time beats his, you win. It's as simple as that!
BitmapText
The game uses a BitmapText for the text. This was created using the free online tool Littera.
You select your local font file and define the colour, gradient and characters you want included. For this game I picked a chunky pixel style font, a white gradient and a sharp drop shadow. By changing the "Included glyphs" you're able to cut down on the size of both the resulting PNG and XML file, by only including the characters you need. It's then loaded with:
this.load.bitmapFont('font', 'assets/font.png', 'assets/font.xml');
and created with:
this.helpText = this.add.bitmapText(630, 404, 'font', "After 10 paces", 16);
this.helpText.align = 'right';
Where the value at the end (16) is the font size to use. The actual font supports up to 72px (and above, but things start getting anti-aliased) but we only need some small intro text. The text is right-aligned. Mostly because it fits in with the game art. This however presents a small problem because BitmapText objects have no sense of 'width' until they are rendered once, and they also have no anchor property. However you can re-create the effect of this by putting this in an update method:
if (this.helpText)
{
this.helpText.pivot.x = this.helpText.textWidth;
}
It's not elegant, but it works (and is something we've addressed in Phaser 3)
Timers
We need several timers in the game. One to count the number of paces the cowboys are walking away, one to handle the time before 'Draw' is displayed, another for the Cowboy himself and a few more to time the playing of audio. These are all achieved using the Phaser.Timer class. The pace timer for example:
this.paceTimer = this.time.create(false);
this.paceTimer.repeat(500, 10, this.stepAway, this);
this.paceTimer.start();
This is a fixed-repeat timer. Every 500ms it will call the function stepAway
and it will do it 10 times only and then destroy itself. The rest of the timers work in the same way. You can check if a Timer is running by looking at its running
property, as we do when you try to shoot the Cowboy:
shoot: function () {
if (this.cowboyTimer.running)
{
this.youWin(false);
}
}
Timers and especially TimerEvents are designed to be disposable. It doesn't hurt if you create a whole bunch of them and then throw them away after you're done. They also respond to the game pausing and resuming again, so are safe should you have a tab-switching happy gamer on your hands.
Waveforms
This is the first Coding Tips game to feature audio! gasp! There isn't much, but it elevates the feel of the game. The audio game from the Universal Sound FX collection and was processed in Adobe Audition, converted to mp3s. The bitrate is probably a bit high for mobile, but is fine for desktop.
Aside from checking if the files are decoded we're not really doing anything special with the audio - just playing it:
this.sound.play('fire');
The game is assuming you have either Web Audio or a browser capable of playing more than one Audio channel at once. In a later tutorial we'll cover using Audio Sprites, but not today.
How to change the speed of the game
This was one of the 'box outs' in the original book along with Making the game harder. To make the game faster (or easier) you can simply adjust the delay
and reactionTime
min and max values. However you could also add an element of chance in: it's already possible for you to 'cheat' (try shooting the cowboy before the paces timer is up!), maybe you could let him do the same?
Brain Food
Here are some ways to enhance this game:
- Old guns were temperamental, allow them to mis-fire.
- Make the cowboy sometimes cheat too!
- Don't die on a single hit, but give a life gauge and/or body parts to shoot.
- Add a variety of cowboys, each with different traits.
Here is what's new in the Phaser world this week:
- Death and Killing Overriding Phaser's kill() Method
- Lostcast 110: Photon Storm 2 In which Geoff and Matt interview me
- Control a div sprite with Phaser and Typescript Bash the DOM with this little tutorial
- Learn Mobile Game Development by Building 15 Games On Kickstarter
- How to implement a countdown timer From gameboxZ.org
- quote-mmo-unquote Testing out phaser.js, socket.io, ivy, ant, tiled, and netty
- Phaser, Parse and CoffeeScript Tutorial by WillyG
- Bitmap Fonts with CocoonJS A handy tutorial on getting them working
- Invaders Breakout Fun new game in the App Store
- Mobile-Efficient Camera Follow From The Botanist Game Blog
- Jewel Academy BoosterMedias top game now on Yahoo Japan Got something you'd like featured? Get in touch.
If you've questions or comments about the code then please ask. Equally if there are things you'd like me to write about then tell me! Until next week, happy coding. Discuss: HTML5 Game Devs Forum Tweet @photonstorm (hashtag #phaserjs)
Phaser Coding Tips is a free weekly email - subscribe here.
Welcome!
Back in the late 80s I was utterly captivated by an Usborne range of programming books, one of which was Computer Battlegames (for the ZX Spectrum, et all).
The front cover and illustrations within this book promised great things! In reality only one game in the entire book even had any graphics (everything else was text mode). But that didn't stop it firing my imagination. For this weeks coding tip I've taken one of the games from the book and bought it into Phaser.
Get the source
I'm only going to highlight the most important parts of the code here. So please always look at the source first. If you've questions about something I didn't cover then ask on the forum. Run / Edit the code on jsbin or codepen Clone the phaser-coding-tips git repo.
Shootout
"You are standing back to back. You take 10 paces, turn and reach for your guns. How quick are you? Can you shoot first?" That was the blurb from the original game in the book. It accompanied 15 lines of code and a lavish spaghetti western style illustration. For our rendition Ilija has given it a pixel art look instead.
The game consists of just 1 image, which we'll change the texture of, some text and a bunch of timers to handle the shooting.
Structure
If you look at the source you'll notice that we're using a slightly different structure this week. This is because we've a few assets to load (audio mostly) and we want a Preloading screen to display that. To do this we create 3 States: Boot, Preloader and Game within a Shootout
object. Boot handles setting up some input values and then loading our preloader assets (a small logo and a preloader bar). Once we've got those the game proceeds to the Preloader state. In here it's business as usual. We display a sprite, a preloader bar and load the assets. The only part that may be new to you is the update
loop waiting for the audio to decode before carrying on. We're using mp3 files which have a latency involved not only in loading but also in decoding before they can be played. As we use them in the game we don't want the game to start until they're ready to play. So we simply check their decoded status in our update loop:
this.cache.isSoundDecoded('casing')
Once they are all ready we proceed to the Game state.
The Game Flow
The basic flow of the game is this: * There is a "10" paces count down timer * After this we pick a random time before the game displays 'Draw' * At this point we pick a random time that the Cowboy will shoot in * If you shoot first, you win. * If he shoots first, you lose. After the cowboys have 'paced away' the delay time before they are expected to draw their guns is defined:
var delay = this.rnd.between(500, 3000);
Once they are allowed to draw, the speed at which the cowboy will shoot you is set. This is done using two properties defined in the Game constructor:
this.reactionTimeMin = 100;
this.reactionTimeMax = 500;
So it will pick a random time between 100ms and 500ms. If your time beats his, you win. It's as simple as that!
BitmapText
The game uses a BitmapText for the text. This was created using the free online tool Littera.
You select your local font file and define the colour, gradient and characters you want included. For this game I picked a chunky pixel style font, a white gradient and a sharp drop shadow. By changing the "Included glyphs" you're able to cut down on the size of both the resulting PNG and XML file, by only including the characters you need. It's then loaded with:
this.load.bitmapFont('font', 'assets/font.png', 'assets/font.xml');
and created with:
this.helpText = this.add.bitmapText(630, 404, 'font', "After 10 paces", 16);
this.helpText.align = 'right';
Where the value at the end (16) is the font size to use. The actual font supports up to 72px (and above, but things start getting anti-aliased) but we only need some small intro text. The text is right-aligned. Mostly because it fits in with the game art. This however presents a small problem because BitmapText objects have no sense of 'width' until they are rendered once, and they also have no anchor property. However you can re-create the effect of this by putting this in an update method:
if (this.helpText)
{
this.helpText.pivot.x = this.helpText.textWidth;
}
It's not elegant, but it works (and is something we've addressed in Phaser 3)
Timers
We need several timers in the game. One to count the number of paces the cowboys are walking away, one to handle the time before 'Draw' is displayed, another for the Cowboy himself and a few more to time the playing of audio. These are all achieved using the Phaser.Timer class. The pace timer for example:
this.paceTimer = this.time.create(false);
this.paceTimer.repeat(500, 10, this.stepAway, this);
this.paceTimer.start();
This is a fixed-repeat timer. Every 500ms it will call the function stepAway
and it will do it 10 times only and then destroy itself. The rest of the timers work in the same way. You can check if a Timer is running by looking at its running
property, as we do when you try to shoot the Cowboy:
shoot: function () {
if (this.cowboyTimer.running)
{
this.youWin(false);
}
}
Timers and especially TimerEvents are designed to be disposable. It doesn't hurt if you create a whole bunch of them and then throw them away after you're done. They also respond to the game pausing and resuming again, so are safe should you have a tab-switching happy gamer on your hands.
Waveforms
This is the first Coding Tips game to feature audio! gasp! There isn't much, but it elevates the feel of the game. The audio game from the Universal Sound FX collection and was processed in Adobe Audition, converted to mp3s. The bitrate is probably a bit high for mobile, but is fine for desktop.
Aside from checking if the files are decoded we're not really doing anything special with the audio - just playing it:
this.sound.play('fire');
The game is assuming you have either Web Audio or a browser capable of playing more than one Audio channel at once. In a later tutorial we'll cover using Audio Sprites, but not today.
How to change the speed of the game
This was one of the 'box outs' in the original book along with Making the game harder. To make the game faster (or easier) you can simply adjust the delay
and reactionTime
min and max values. However you could also add an element of chance in: it's already possible for you to 'cheat' (try shooting the cowboy before the paces timer is up!), maybe you could let him do the same?
Brain Food
Here are some ways to enhance this game:
- Old guns were temperamental, allow them to mis-fire.
- Make the cowboy sometimes cheat too!
- Don't die on a single hit, but give a life gauge and/or body parts to shoot.
- Add a variety of cowboys, each with different traits.
Here is what's new in the Phaser world this week:
- Death and Killing Overriding Phaser's kill() Method
- Lostcast 110: Photon Storm 2 In which Geoff and Matt interview me
- Control a div sprite with Phaser and Typescript Bash the DOM with this little tutorial
- Learn Mobile Game Development by Building 15 Games On Kickstarter
- How to implement a countdown timer From gameboxZ.org
- quote-mmo-unquote Testing out phaser.js, socket.io, ivy, ant, tiled, and netty
- Phaser, Parse and CoffeeScript Tutorial by WillyG
- Bitmap Fonts with CocoonJS A handy tutorial on getting them working
- Invaders Breakout Fun new game in the App Store
- Mobile-Efficient Camera Follow From The Botanist Game Blog
- Jewel Academy BoosterMedias top game now on Yahoo Japan Got something you'd like featured? Get in touch.
If you've questions or comments about the code then please ask. Equally if there are things you'd like me to write about then tell me! Until next week, happy coding. Discuss: HTML5 Game Devs Forum Tweet @photonstorm (hashtag #phaserjs)