How to code Java #14 – creating a game

crash_16x9

At the risk of showing my gaming prowess (or lack thereof), my very first computer game was Digital Derby by Tomy – though, calling it a ‘computer’ game is a bit generous. Forget finding a CPU inside, this one had barely any electronics at all.

ddBut I couldn’t care less – it was one of those glorious electromechanical games that slurped through two ‘C’ cell batteries as you drove your race car, overtaking the slowcoaches while trying to avoid becoming roadkill from on-coming traffic.

If you smacked into someone, you had to press the reset button for a three-second penalty and you were off again, since speed was the key – the faster you went, the higher your score.

Totally boring, probably, by today’s standards, but for 1978, it totally rocked.

Being a simple game, it’s also ripe for coding up. What might surprise you is that we can use the same basic code structure as last month’s air combat arcade game.

Get the source code

You can download the source code for our Overtake car game from our website.

Download it, unzip it once, then launch the NetBeans IDE, select File, Import Project and choose ‘From ZIP’.

Select the inner zip file you just found and import it into your IDE. Select the tab for Overtake.java source code, hit the green Play button and it should start up.

Don’t have Java or NetBeans on your computer? Grab hold of the latest JavaBeans 8.0.2 IDE and Java 8 SE JDK bundle from here.

Give yourself a time limit

One of the problems you can have when coding is ‘scope creep’, that nasty habit of dreaming up more and more brilliant ideas that turn your once-simple game into a mega-epic that now needs five full-time coders to finish.

So as an exercise, I gave myself eight hours to get this game up from concept to car-crash (in a good way). Sometimes, giving yourself a time limit can help you focus on the must-haves and get something working.

Once you’ve got the basic shell of your game up and running, you can go again with another time-limit and add new features to sweeten it up (in project management, this is ‘kind-of, sort-of’ the ‘agile’ approach.)

Mock-up

mockupThe first step was to come up with a game layout mockup, which broadly follows the ‘Digital Derby’ original, with the driver’s car at the bottom, moving left to right.

On-coming traffic comes straight down the opposite lane, while slow cars have to move both forward and back (up and down), relative to the speed of the driver’s car. And of course, the driving lane is on the left (correct) side of the road.

While the original game had a genuine three-speed manual mechanical gearbox(!), coding our game as a four-speed automatic would cut down on controls required and save coding time.

Frame, background image

bgmakeWith a reasonable mockup in hand, we can now get to work on the game frame.

Given that everyone has at least a 1024×768-pixel panel to view, it made sense to keep the game dimensions to 600 x 720-pixels and lock off frame-resizing.

To keep things simple, the background image doesn’t move or scroll, allowing me to create a crude but serviceable road landscape in Paint.Net.

Top-down view images of cars were sourced from Google and scaled to size (if this was a serious effort, the cars would also have been drawn).

Game structure

We talked about game structure before. This is important because it helps you figure out game mechanics and how everything interacts – and it’ll help if we use Classes.

Our game here has only three classes – Car, SlowCar and CarOnComing.

Each car class has position information or ‘attributes’ – the SlowCar and CarOnComing have fixed X-axis (horizontal) position, the Car class, fixed Y-axis (vertical) positioning. They all have speed attributes, but the Car class additionally has Score and Hit attributes.

As for class functions or ‘methods’, each has a ‘move’ function to handle movement while the Car class also has a ‘checkHit’ method to see if the car has hit anything.

Animation via timer class

As we did with our air-combat arcade game, we’ve incorporated a timer that governs the animation.

Every 25-milliseconds, the timer fires and runs the ‘animate’ instance of the ‘TimerListener’ class. Each time that class fires, it increments all screen movements as necessary. Triggering every 25-milliseconds means we have a game frame rate of approximately 40 frames per second (40fps).

There are several things it checks each time – first, it looks to see if ‘timeRem’ is greater than zero. The game is timed to last two minutes (120 seconds), but instead of using another timer, we just set an integer called ‘timeRem’ to a start count of 4800 and use the animation timer clock to decrement it.

If that timer fires 40 times per second, it’ll take 4800 / 40 = 120 seconds to count down to zero. Two minutes, give or take (the timer isn’t perfectly accurate).

J-bits

structAs for the game layout, the app – our Overtake class – extends a JFrame (remember, ‘extends’ means we want all of the standard features of a JFrame, but we also want to add our own code).

And on that JFrame, we add a JPanel extended class we’ve called ‘Road’. It’s this JPanel that everything is drawn onto using the standard ‘paintComponent’ method.

Going back a step, the JFrame constructor creates the frame, creates new instances of the car classes as well as adding an instance of the Road class to the frame – this lays the foundations by creating all the basic object instances we need.

keyeventIt’s also where we keep the KeyListener called ‘KeyChecker’. Remember that to ‘listen out’ for when keyboard keys are pressed, we attach a KeyListener to the frame, which fires as soon as any key on the keyboard is tapped.

We’re interested in six keys only – the four arrow keys, along with ‘Y’ and ‘N’ for the user to answer whether they wish to play again.

The data on which keys are pressed comes back in the ‘e’ KeyEvent system variable and we use the various KeyEvent constants such as ‘VK_UP’, ‘VK_DOWN’ and so on to check which key was pressed. However, we need to add a bit more to it.

Normally, if you hold down a key, your computer registers a single key press, and after a time, repeat key presses are loaded into the keyboard buffer. The problem is that time delay between the ‘one’ and the ‘many’ is a real pain, particularly if you’re trying to steer away from on-coming traffic!

So, instead, we use the key press to set the value of a cell in an integer array. If a key is pressed, the designated array integer is set to ‘1’, flagging we’re to launch a function continuously. If the key is released, that integer is reset to ‘0’ and stops.

This way, we escape the keyboard buffer delay and the game instantly recognises you want multiple repeated actions immediately (such as steering movement). It also recognises multiple keys at once, so you can accelerate or brake and steer at the same time.

Animation

The timer class we mentioned before that handles our animation is located in the JPanel class, along with the ‘paintComponent’ method that does the drawing.

Each time the timer triggers, the TimerListener also calls the ‘move’ methods in each of the three car classes. Depending on their speeds, the Y-axis position attributes are incremented and decremented by small amounts on each timer trigger and then drawn by the ‘paintComponent’ method, giving us animation.

One of the tricks used by Digital Derby was to have two plastic loops with car decals to give the impression that you’re driving down this continuous road. We’ve taken this 1970s’ view of looping and given it a 21st-century coded update.

In Java, ‘0’ is always the top of the frame and the bottom of the frame is available from the ‘getHeight()’ system method. The SlowCar image is 150-pixels tall, the ‘bigTruck’ is 200-pixels – that means in order to have these vehicles disappear above the screen, we need to take their Y-positions to -150 and -200, respectively.

This is done by decrementing the ‘y’ attribute. However, once they reach -200, there’s little point having them disappearing further off screen, so to give the impression of looping, we reset the position to ‘getHeight() + 300’, which is some way below the bottom of the screen.

Since the decrementing of the ‘y’ attribute is governed by other code, the car continues to move upwards, appearing from below the screen frame.

The original purpose of the loop in this game was to give the impression of multiple cars and that’s what we’ve now got.

We won’t explain it but we also do the same thing for on-coming traffic – anything below ‘getHeight() + 300’ gets reset to -200.

Movement vectors

relNow obviously, we’re not making ‘Forza’ here, but some simple physics using the concept of ‘relative velocity’ will help make our game look right.

Think about when you’re travelling in a car or train – cars travelling in the same direction appear to move slowly, relative to each other; vehicles travelling in the opposite direction appear to move exceedingly fast.

In physics, you’d say each vehicle had a vector – a velocity (speed) and direction. When you’re adding simple vectors together, the relative velocity of two vehicles travelling in the same direction is the fastest minus the slowest.

So if you’re in one car doing 110km/h and another car next to you is doing 90km/h, relative to that slower car, it’ll seem like you’re pulling away at 20km/h. But for two cars travelling in opposite directions, you still subtract one vector from the other, but the difference is that the vehicle travelling in the opposite direction is treated as a negative vector.

For example, you’re still doing 110km/h in your car, but this time, the car doing 90km/h is going in the opposite direction. Now, the subtraction of vectors becomes 110km/h – (–90km/h) = 110 + 90 = 200km/h.

Relative to the car travelling in the opposite direction, it looks as though you’re travelling at 200km/h.

If you look at the SlowCar and CarOnComing classes and their respective ‘move’ methods, you’ll see that for the SlowCar class:

y += (car.speed – speed) / 20.0

But for the CarOnComing class, it’s:

y += (car.speed + speed) / 20.0

In each case, ‘speed’ refers to the class attribute, so SlowCar.speed and CarOnComing.speed, respectively. But here, we either add or subtract the speeds to get the correct relative velocity and use that to increment the Y-position.

The reason we divide the increment by 20 is to scale the movement down to fit our JFrame panel and give you enough time to judge when to move. (Here’s a tip, change the ’20.0’ to ‘5.0’ and see how playable it is – not!).

Calculating scores

behindScoring in the game is based on the driver’s car speed – the faster you drive, the faster your score increments.

There are obvious times in the game when you need to slow down in order to allow on-coming traffic to pass (as well as making sure you don’t run up the back of the slow car in front).

This obviously slows the score increment.

Experiment!

If you compare the code from our game with our air-combat arcade game, you’ll see that there’s a good degree of similarity.

ynThey both use the same basic structure, starting with a JFrame and a JPanel, drawing everything on the JPanel, animating via Timer and TimerListener class that also fires up the movement methods of each of the three object classes.

Now again, we’re not saying this is the last word in how to code games – of course, it isn’t. This game takes approximately 300 lines of code, similar to the air-combat arcade game, but frankly, I’ll be surprised if someone can’t do this in half the space.

But really, the goal of these last few articles on game coding has been to get you thinking about objects and classes.

Balls, cars, trucks, fighter planes, even bullets, they’re all objects and once you start thinking about coding using objects as your frame of reference, it actually becomes much easier to understand just what your code has to do and start coding it up.

That’s the idea of Object-Oriented Programming (OOP).

There’s plenty more we can do with this code – add and animate some side-panel scenery, move the lane-divider lines, add more vehicles, even add more complexity to the game speed. But the important thing for now is the game logic works – all of these extras are peripheral, really.

What games do you have lurking in a cupboard that a ripe for a Java coding blitz?