The main purpose of this week’s session was to explore the idea of transforms by using them to make a little top-down tank that we could drive about the screen. I close a tank because:
- It’s easy to draw a recognisable tank with a few simple shapes
- It’s easy to see which way is forward
- Tanks move in a very simple way (either turn or drive forward or backwards)
Origin and Axes
We don’t often use the word, but the top left of the screen (0, 0) can be referred to as the origin.
Another useful word is axes (plural of axis). We have two axes in 2D – the X-axis which normally runs horizontally left-to-right on the screen and the Y-axis that runs top-to-bottom.
With these words in hand, let’s talk transform. P5 has three functions that allow us to make transforms. Once we call them, they effect everything that’s subsequently drawn. Here they are:
- translate() – Move the origin by a given amount along the x and y axes.
- rotate() – Rotate about the origin (wherever it currently is).
- scale() – Scale along x and y axes.
Design of our Tank class
Our Tank class has five main things:
- A constructor that takes and stores a vector for the tank’s position [this.pos]
- A property to store the tank’s angle [this.angle]
- A function to draw the tank [draw()]
- A function to tell the tank to turn left/right [turn()]
- A function to tell the tank to drive forwards/backwards [drive()]
We draw our tank as if it’s centered on (0, 0) and facing right. We then can use translate(this.pos) to move it and rotate(this.angle) to change its angle.
For turn() all we need to do is to to change this.angle by a requested amount.
For drive(), we do a little more. We:
- Create a copy of the current position
- Create a vector (1, 0) which is facing right (representing the tank’s forward direction)
- Multiply that vector by how fast we want the tank to move
- Rotate that vector to point in the tank’s actual direction this.angle
- Add to the copy of the current position we took initially
- Check that new position to make sure we wouldn’t end up off-screen and, as long as we we wouldn’t, update the tanks actual position this.pos
Getting user input
We then need to get input from the user. In sketch.js we created a new function getInput() and put a call to it in our draw() function.
In getInput() we just look for the arrow keys. If we see Left or Right then we tell the tank to turn. If we see Up or Down we tell the tank to drive. We use the P5 function keyIsDown() for this.
The files for this week can be found on our GitHub repository. The actual files uploaded have expanded the game a little. There are now two tanks and the Tank constructor takes two new arguments for the tank’s colours. The second tank is controlled not with the arrow keys but with WSAD and we use the P5 variables keyIsPressed and key to detect those being held down (as they’re different to the arrow keys).