Game Dev with Phaser – Part 2: Generative tracking

In part 1 of this series we walked through setting up your development toolchain and initializing a blank canvas. Now the boring bit is over, and we can make a game 🙂

So what are we making? I’ve personally never written car physics before, even though I’ve tweaked them several times at my first dev job. So I figured that a top down racer would be a fun challenge, as well as a cool way to learn what Phaser and it’s newly added physics system (p2) can do. Sounds simple right? Well, not so much when we jump into wheel physics, but we’ll get to that in a later.

With game development, it’s often best to get the core elements of the game right first before adding all the menus and game flow. This allows you to see if it’s fun before you dedicate a considerable amount of time. This post sets us in the right direction, with a track for our racer.

Logical turns

We’re going to have several different track pieces, which we’re going to want to stitch together. Each piece will have an entrance and exit direction, which we can use to link them up correctly when generating new sections:

sections

Here we have 2 types of track, straights and bends. Each type has a mapping from it’s current rotation to it’s exit. We also have the mapping from the entrance to the current rotation. For simplicity lets assume we’re only going up or sideways, this allows us to not have to worry about the track crossing itself. We can also assume for bends starting at the bottom, let’s split that 50/50 between rotation’s 0° and 270°.

Making a module

Ok, so we’re going to want this inside our project. First let’s create a Track.js.

This is a basic module, as you can see, there’s some standard constructs familiar from other languages and some Javascript specific things.

  • Track.TYPES is equivalent of an enum (statically added to the class)
  • Track.IMAGES is a static array
  • We have a constructor, although the syntax may no be what you’re used to, especially specifying it as a constructor after defining it.
  • Two member functions, empty for now
  • And finally we return our ‘class’ so that it can be accessed outside of this module.

Now we need to take our above logic, and turn it into code for the createNextRandom function. Let’s assume rotations are multiples of 90°:

First we set some defaults. These will be used if we are generating the first tile. If we have a previous tile, we generate a random type. Since we only have 2 types at the moment, we can just do a simple random int. Then we get the exit direction from the last tile piece created – our entrance direction.

Above we work out what rotation we need to use based on the type and the entrance direction. For straights,  if we’re coming in from the bottom, we need to generate another 0 rotation straight, otherwise we’re just going in the opposite direction from where we came in. For bends, if we’re coming in from the bottom, we can pick a random between going left or right, but from the left or right, there’s only 1 option.

After this we can actually create the part, filling in our second function:

This will actually create the image and add it to the game, or more specifically, to our sprite batch. We anchor each image at the center, allowing all rotations to occur about the same pivot. We then rotate it to the calculated rotation from above.

Now we continue our mapping of rotations to outputs. Note that at the top, we create a small container object, in which we put the image and the out direction. This can be used as an anonymous data storage, much like a struct in some other languages, and is most often used when creating a new module is too much overhead. We then push this object into our list of tiles, so that we can retrieve it later on.

Finally for the track, we create a small generate function:

This allows us to generate new chunks, with a default amount of 20 chunks at a time.

Back to the game

Putting this in the game, we can move back to our index.js. First we need to tell the index.js that we have a new module:

I’ve added the Track module to the module parameters list mentioned in Part 1. With that, we’ve included the module.

And then we need to load the images:

Here we alias to loaded paths to the names. We do this in the preload method from Part 1. Let’s also throw in some grass for a nice background.

We expand the world massively, to allow lots of room to generate more track. We then resize the world bounds, and throw in a Tile Sprite, which allows our grass to spread across the entire world. This is a great helper class in Phaser, giving us the option to cheaply render a background, and not be concerned about having to write our own tiling background. Then, we create our track, and just as a placeholder until we have a player, we tell our camera to focus on the track.

Firing up our index.html in the browser, we should see a chunk of track on screen. Visually, it’s not much for now, but next up, we’ll make something move. You can see from here how it’s easy to add different track shapes, possibly some chicanes, and any other kind of curve. As long as the output is defined and we write a mapping, we have an infinite track generator!

 

 

Posted in Uncategorized.