This week we creating a game where a tiny plane flies over dynamically generated terrain picking up as many boxes as possible. The player scores a point for every box, but that also makes the plane fly faster, making the game more challenging.
Normal random-number generators produce values that jump around all over the place. Perlin noise is different. It is also random, but it varies smoothly. This makes it great for mimicking the sort of randomness we see in nature.
1D Perlin Noise Landscape
Our smooth and changing landscape is generated using a one-dimensional Perlin noise value generated by the P5.js function noise(xoff).
We start with a loop that goes across from 0 -> width across the screen. We’re looking to generate a set of [x, y] points that define our shape.
We use these values:
- xstart: A starting value for xoff
- xinc: An amount to increment xoff by for every new location
- ymin: The smallest y value we want for our landscape – something a little below the top of the screen
- ymax: The largest y value we want for our landscape – something a little above the bottom of the screen
Each call to noise() generates a single value in the range 0-1. We use the P5.js function map() to change this value in the range 0-1 into a value in the range ymin-ymax.
Changing the size of xinc controls how choppy or smooth the landscape is. We tune it to a value that gives approximately two peaks and two valleys across the screen, and looks right for our game.
Moving the Landscape
Moving the landscape is achieved by changing the starting value of xoff (aka. xstart) each time we update the screen. By making it a little larger each time, the effect is that the landscape seems to scroll from right to left.
Other Parts of the Game
The other parts of the game are very standard. We define a simple plane shape (drawn using rect() calls) that can move up or down in response to the arrow keys.
We define “cargo” containers that are randomly generated on the surface of the landscape and move right-to-left at the same speed.
The cargo containers have an active property that is false if they move beyond the left-edge of the screen or get sufficiently close to the plane to be “picked up”.
We added a function to the landscape class (Ground.js) that checks for a given [x, y] location to see if that point us under the ground by checking what the height of the landscape is at that x value. If the plane is below the ground we consider it crashed.
We added a simple scoring mechanism that tracks how many boxes were collected and makes the plane move faster (really – the ground scroll faster) every time a box is collected.
The files for this week can be found on our GitHub repository.