[This was written years ago for a magazine and was the latest in a series of programming articles and there were several other parts that were published in earlier issues. At the time there was a racing car game on the ITV-F1 website. This was a Vodafone advergame and it was the inspiration behind this article.]
An advergame is a fairly new class of software that designed to promote a brand or product. They are becoming increasingly popular with advertisers. The games are simple and are often played online, although offline games are sometimes produced too. The idea is that people are attracted by a simple, fun game and in the five minutes or so they spend playing it, they get to stare at the company logo or product, which then becomes imprinted on their brain.
The market for advergames is increasing and if you can create simple, fun games, especially online versions, then there is money to be made. The Vodafone Racing Game at the ITV-F1 website is a very simple 2-D game that is easier to write than you might think and is within the capabilities of most programmers. You don't need a degree in computer science to create it, although it does help if you paid attention in school. Let's see how to create our own Grand Prix racing game.
Back to school
Our aim is to be able to move a game character, a car in this case, in any direction, so first we need some way of defining a direction. The most obvious way of doing this is to use the 360 degrees that make up a compass. We can choose an angle, such as 45, 127 or 319 degrees and head in that direction. We also need to set the speed at which we wish to move. So we need to move at a set speed and at a particular angle.
If we have a game character currently at point x,y on the screen, how do we work out where to move it to? This is where you will wish you paid attention in trigonometry lessons at school. It might have seemed boring and irrelevant at the time, but surprisingly, some stuff that you learn at school is actually quite useful.
Take a look at the diagram. If we move the character from x1,y1 at angle a and speed s, we end up at x2,y2. If we draw a right-angled triangle as in the diagram, we can easily see that the new x coordinate is x1+dx and the y coordinate is y1+dy. We therefore need some way of calculating dx and dy. This is where those boring trigonometry lessons come in.
The sine of an angle (sin for short), in a right-angled triangle is defined as the length of the opposite side divided by the hypotenuse. Using a bit of basic algebra, this means that the opposite side, which is dy in our diagram, is equal to distance s multiplied by the sine of the angle.
The cosine of an angle (cos for short), in a right-angled triangle is defined as the length of the adjacent side divided by the hypotenuse. Rearranging the formula, we can calculate the adjacent side, dx in our diagram, and this is the hypotenuse, s, multiplied by the cosine of the angle.
Using these formulae, we can calculate the position to move the character to, x2,y2. Let's take a look at a simple program to move a game character at a specific speed and angle:
Global x=320 Global y=240 Global s=4 Global dir=30 Repeat Cls MoveCar() Flip Delay 50 Until KeyDown(1) End Function MoveCar() dx#=s*Cos(dir) dy#=s*Sin(dir) x=x+dx# y=y+dy# DrawImage car,x,y End Function
The coordinates are x,y, the speed is s, and the angle is dir. If you try this listing, you will see that the character moves diagonally down towards the bottom right of the screen. This is because the computer sets due West as zero and measures the angle clockwise, so 30 degrees is pointing down and right.
This program is written using an old copy of Blitz Basic and the Sin and Cos functions accept the angle in degrees, but some programming languages require the angle to be entered in radians. This means more school maths I'm afraid. A full circle is 360 degrees and this is 2 x Pi radians, so one degree is 360 / (2 x Pi) or 180/Pi. To convert an angle in degrees to an angle in radians, you therefore multiply it by 180 and divide by Pi, which is 3.142. You will need to check your programming language documentation to see whether you need to use degrees or radians with Cos() and Sin().
The listing above, shows how to move a character at a specified angle and speed. To create our own car racing game, we need to be able to steer the car and to accelerate and brake. This is actually quite straightforward. The left and right cursor keys can be used to steer left and right and we just need to check which one is being pressed. If we press the right cursor key, we add 10 (or whatever increment you want), to the angle, but if left is pressed, we subtract 10. The up and down cursor keys can be used to increment or decrement the speed, s. Here is a modified MoveCar function.
Function MoveCar() If KeyDown(205) Then dir=dir+10 If KeyDown(203) Then dir=dir+350 dir=dir Mod 360 If KeyDown(200) And speed<10 Then s=s+1 If KeyDown(208) And speed>0 Then s=s-1 x=x+s*Cos(dir) y=y+s*Sin(dir) DrawImage car,x,y End Function
If we keep turning right, eventually we will turn a full circle and the angle will be greater than 360 degrees. We therefore need to set it back to zero when 360 is reached. When we steer left, eventually the angle would be negative if we keep subtracting 10. An angle of -10 and 350 are the same, it is just that 350 is the long way round the compass, so we add 350. Then we can set dir to dir MOD 360, which is the remainder and simply keeps the angle, dir, between 0 and 359.
So far, we have completely ignored the graphical implications and if you try a program like the one above, you will immediately see that the car only points in one direction no matter which way it is actually going. We need the car graphic to turn as we turn to the left or right.
There are several ways of achieving this and one method is to rotate the character on-the-fly. We know the angle that we are travelling at, so if your programming language has a built in graphics rotate function, or if you can write one yourself, you just rotate the image the required number of degrees before displaying it. Even if there is a built in function, you may find that it is too slow to use on-the-fly. Rotating the image every time you change direction might cause the game to stutter slightly, even with a reasonably fast built in function.
One solution is to draw the image in an image editing program and rotate it 10 degrees at a time, saving it each time. After this rather tedious operation, you will end up with 36 images numbered 0 to 35. Then all you need to do is to load them into the game and choose the appropriate image when moving. Just divide the direction angle by 10 to get the image or frame number to display.
A good trick is to create one image in a paint program and then to load it into the program. Using the built in graphics rotate function, you can create all the images you need before the game starts by rotating the master image and storing the result in memory. A slight delay before starting the game is acceptable and it won't take more than a tenth of a second anyway.
Blitz Basic has a rotate function and it is just fast enough to use on-the-fly. To make the car point in the right direction, we copy the original car image, rotate it and then print it:
newcar=CopyImage(car) MidHandle newcar RotateImage newcar,dir DrawImage newcar,x,y
The RotateImage command rotates the image about the coordinates 0,0, which is the bottom left corner. This produces an odd and unrealistic turning effect, so the origin is set to the centre of the image with MidHandle newcar before rotating it. The car is then rotated about its centre.
Adding the track
Racing tracks are easily created in a paint program and you can see my effort in the screen shots. I expect you to take more than the two minutes I spent on mine. To create this track, a 640 x 480 pixel canvas was filled with a green and yellow texture. Then a large black paint brush was used to draw the track. If this was a real game project, you would spend time drawing the red and white kerbs on the corners, adding buildings down the back straight, painting a start/finish line and starting grid, advertising hoardings and so on.
As the program stands, you can drive anywhere on the screen. This is obviously not right and you would expect a penalty for taking short cuts across the grass. The track is black, so it is a simple task to read a pixel or two around the car's position and to check that you are still on it. Any other coloured pixel means you are off the track, so the speed is cut by half. If you stay on the grass, you quickly come to a halt and it takes some effort to get back on the tarmac.
The resulting effect is quite good and it makes quite a playable little game. You can download this game from rc.rawinfopages.com/software/car.zip and the .bb files can be loaded into Notepad to view the source code. It is not a finished game and it needs a smarter track, a start/finish line, lap times, high scores, and much more. However, you can easily see how it could be turned into a game as good as the Vodafone Racing Game with a little bit of effort. Try using the techniques to create your own racing game.
Modifying the car's handling
To make the game more interesting, experiment with the angle and speed parameters. These will affect the car's handling. For example, in the listing, the speed is increased by 1 every time the up arrow key is pressed and reduced by 1 when the down arrow is pressed. It makes the car accelerate and brake a bit too quickly and it might be better if the increment/decrement was 0.5.
The acceleration could be variable, so that it rapidly accelerates from a standstill, but it takes a long straight to build up to its top speed. To do this, add 1 to the speed at first, but then 0.8, 0.6 and so on as the speed rises. You could add gears. Just set the maximum speed to 2 to start off with. Then whenever the spacebar is tapped, change up a gear by raising the maximum speed to 4, 6, 8 and so on.
Make downshifts automatic, so as the speed falls, you decrement the gear. The up arrow key is used to accelerate and it could be turned into a real accelerator pedal. When it is pressed, you accelerate and when it is not, you gradually slow down. Just knock 0.1 off the speed when it is not pressed.
Corners should not be taken flat out, so when the left and right cursor keys are pressed, you should first check the speed. If it is at the maximum, you could add only 5 to the angle instead of the usual 10. This would force players to slow down for tight corners like hairpin bends. As you can see, there are lots of ways in which the gameplay can be tweaked to make it more fun and more challenging. Just use your imagination.
Two player game
There are lots of features you can add to the game. For a start, there is no start/finish line, so choose some screen coordinates and compare the car coordinates each time it is moved. When it reaches the start/finish, increment the lap counter. After a set number of laps, the game is over and your time is recorded in a driver's championship table. A lap timer can be started each time past the start/finish line and the best lap times can be stored in a high score table.
We have only shown how to move a single car around the screen in any direction, using the cursor keys to control it. Moving two cars isn't that much harder and you just need a duplicate set of variables to hold the current coordinates, speed and direction. Another set of keys can be selected to steer it, accelerate and brake. With very little effort, you could create a two-player game that is much more fun to play.
Of course, with a two-player game, there is always the possibility that the two cars will collide. You will need to add a check to ensure that both cars do not occupy the same bit of track at the same time. We have examined collision detection before and the techniques we learned can easily be applied here.
Some programming languages have built in sprite collision functions and when two cars crash, you can perform some action, such as changing the angle or speed. It is difficult to decide who should come off worse in a crash, so you might simply want to pick one of the cars at random and reduce its speed by half or set it to zero, or add plus or minus 90 degrees to the direction. That would certainly throw a spanner in the works.
Computer controlled cars
A single player game is easy to write, and a two-player game is not too difficult. If you want a real programming challenge, try adding half a dozen computer controlled cars to make this an exciting racing game. Of course, you will need some way of making the computer-controlled cars travel around the track.
One way of achieving this would be to look ahead. Using the car's coordinates, you could look at pixels on the screen ahead of the car to the left or right. If the left pixel is no longer black, turn right. If the right pixel is not black, turn left. Alternatively, make a car follow the road edge, a bit like the way you solve mazes by following a left-hand wall.
Another way of getting computer-controlled cars to race around a track is using waypoints, which we have examined before (in a previous magazine article). Just set waypoints on each corner and the cars will head for them. You can't have all the cars heading for the same waypoint, so create three or four at different positions on a corner and pick one at random for each car.
You don't want all the computer controlled cars moving around the track at the same speed because they would all move together as a block in an unrealistic way. One solution would be to give each car a different top speed. For example, one car could have a top speed of 10.0, while another can reach 10.2. It will therefore inch ahead down the long straights. Cars could also have different acceleration too and all you need to do is to adjust the increment to the speed. So instead of increasing every cars speed by 1, add 0.9 or 1.1 to the speed instead.