A note on code structure: Remembering that this is just an example of a simple mechanic, and
not production ready code, we don’t need to over-engineer any kind of complicated OO class
design. In fact, to keep this simple I use global variables and methods (oh the horror!)

We can then use the open source Tiled map editor to create
the level layout:

The editor creates an xml .TMX
output file that defines the level, but I’m not going to be taking advantage of any advanced features, so instead I can simply
export it as JSON, manually pull out the data for the layer, and paste it directly into my source code as a simple array of
cells, along with a couple of simple accessor methods:

If I add multiple levels at a later date then I could easily load the exported .json files
using an ajax call at the start of each level
and a quick call to JSON.parse() in order to extract the cells, but I don’t need that
for this demo.

Game Loop

As usual, we will be using requestAnimationFrame
to ensure our rendering loop is as smooth as possible with a controlled, fixed timestep
update loop that is independent of our rendering loop. I explored this previously when
implementing BoulderDash.

We will need a way to measure the current time. In modern browsers we can use the
high resolution javascript timer, with a fall-back for older browsers:

NOTE: Since requestAnimationFrame will go idle when the browser is not visible, it is possible for
dt to be very large, therefore we limit the actual dt to automatically ‘pause’ the loop when this
happens

Interesting to note is that when we do have a large dt we make sure to run update() in a while loop to
ensure the game ‘catches up’ without missing any updates, but we don’t bother doing this for render()
where simply rendering the most recent state once is enough to catch up.

Keyboard Input

In addition to the running game loop, we need to gather input from the user.
We simply record if the player is trying to move left, right, or jump. The
update() loop takes care of actually moving the player.

One tricky aspect of using a frictional force to slow the player down (as opposed to just
allowing a dead-stop) is that the force is highly unlikely to be exactly the force needed
to come to a halt. In fact, its likely to overshoot in the opposite direction and lead
to a tiny jiggling effect instead of actually stopping the player.

In order to avoid this, we must clamp the horizontal velocity to zero if we detect that
the players direction has just changed:

Collision Detection

Our collision detection logic is greatly simplified by the fact that the player
is a rectangle and is exactly the same size as a single tile. So we know that
the player can only ever occupy 1, 2 or 4 cells:

This means we can short-circuit and avoid building a general purpose collision
detection engine (e.g. a quad tree) by simply looking at the 1 to 4 cells that
the player occupies:

Since the map is static, we could have easily cached a rendered version in an off-screen canvas, but
for something this simple performance is not an issue, so we can just re-render it every
frame and keep the code clear and simple.

Conclusion

That is a very, very, minimal platform game, but it gets me started! and leaves so much more to add later: