Wild West Shootout Tutorial

By Richard Davey on 13th February 2015   @photonstorm

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).

Book cover

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?"

"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.

Shoot

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.

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.

waveform

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

Page

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.

Comments

comments powered by Disqus