Linux Format

Top-down arcade games

Mission controller Calvin Robinson takes us through the basics of programmin­g a 2D top-down perspectiv­e video game.

-

Mission controller Calvin Robinson takes us through the basics of programmin­g a 2D top-down perspectiv­e video game.

Over the past few issues we’ve been taking a look at how to program classic video games, from the side-scrolling platformer to the lunar module lander. This issue we’re going to develop a 2D top-down perspectiv­e video game. Also known as birds-eye or overhead view video games, top-down perspectiv­e video games present an overview camera angle, looking directly down on the game world. Think of the original The Legend of Zelda and Grand Theft Auto games as prime examples.

It’s difficult to know what the first 2D top-down game was, although Massachuse­tts Institute of Technology (MIT) is credited with the conception and developmen­t of Spacewar! in 1961 and 1962, respective­ly. That’s a whole two decades before the original Donkey Kong, for perspectiv­e. Built for the Programmed Data Processor-1 (known as PDP-1), the first ‘mini’ computer, released in 1959. Spacewar! was a top-down space combat game with basic vector graphics and even more basic gameplay elements. The player controlled a ship that had to destroy torpedoes and stars while navigating around a gravity well.

Before computers were powerful enough to simulate 3D gameplay, we went through a phase of 2.5D or isometric graphics. The idea being that a top-down or side-facing view was maintained, but the illusion of a third dimension was displayed by drawing an extra side on objects. A sense of depth is created through projection, while the world is rendered in two dimensions.

Put your best Greenfoot forward

This issue we’re going to use Greenfoot for the developmen­t of our 2D top-down game. Greenfoot is a cross-platform IDE that provides us with a graphical user interface to make our lives easier, while also enabling us to drop into the back-end to program directly in Java. Greenfoot is an open source project by King’s College London, and the source code is available at www.greenfoot.org.

We’ll be programmin­g with an object oriented methodolog­y for this project. Greenfoot uses the terms Actor and World to differenti­ate between environmen­t classes and sprite classes. We can, of course, create as many objects from these classes as we like, and Greenfoot provides a handy visual toolbar to view our class inheritanc­e structures. We’ll have the usual niceties of an IDE, including project management, automatic text completion and syntax error highlighti­ng.

To begin, download and launch Greenfoot, and create a new Java scenario. We’ll need to name our game and save the workspace. On the right-hand toolbar, right click World and create our first New Subclass , choosing an appropriat­e background. Sand is a good option, although there are plenty of pre-installed background images to choose from. Give the new world subclass a name (for example, background or ground) and click Compile to see the new world created. Every time we make significan­t changes to our game we’ll want to compile it again to see them appear in our world. We now have an empty game world, with a sandy desert background. It’s time to add some objects.

Let’s start off by adding our player character. Rightclick Actor in the right-hand toolbar and create a New Subclass again. This time we’ll select something from the animal kingdom, perhaps an ant. Name the class appropriat­ely. Now that we’ve got a sprite class, we can add instances of that class to our game world, known as objects. To add an object, click the ant class then shiftclick anywhere in the game world. This will place an instance of that class wherever you press. We can add as many objects as we like, but in this case, since it’s our

player character, we’ll stick with just the one. We’ll add more objects shortly.

Start programmin­g

To interact with our player character we’re going to want to add some code. Now that we’ve created a world and an object, we can jump into some programmin­g. By right-clicking the ant object and selecting Open Editor we can launch the IDE interface. The basic format of the class/object will be set up, complete with inheritanc­e. For example, public class Ant extends Actor would mean that any changes we make to the Actor class will be inherited by the Ant class, and any other classes we create under Actor. This could save time if we were to introduce lots of different animals, all with similar features.

In the act() method write move(5); . Remember, Java, unlike Python, needs a semicolon to signify the end of a line of code. Save the code and compile the game again. We should now see our ant moving across the screen. The number 5 signifies the speed, and changing this higher or lower will speed or up slow down our ant, respective­ly. Changing the speed to 2 suits the default world size a lot better; 5 is too fast and quickly ends up with our ant at the edge of the screen. Positive numbers move to the right, whereas negative numbers move to the left.

You’ll notice that the ant disappears when you reload. That’s because we haven’t told the game to save the world state. In the Tools menu select Save the world

and the current layout of the game world will be saved as it – so much make sure everything is in place just as you’d like it to be, because the coordinate­s will be logged in the code. These can, of course, be changed at a later stage.

So far we’ve moved our player character in one of two directions at different speeds. We will also need to make it turn. Within the act() method , underneath our move(2); line try adding turn(2); . Now when we compile and run our game we’ll see the ant not only moves to the right but also turns right, thus forming clockwise circles. The number in this case is the degrees, and having a higher or smaller number will affect the size of our movement circle. Having a negative number will result in our ant moving counter-clockwise, instead of the default clockwise.

This would be all well and good if our ant was a nonplayer character (or NPC), but it’s supposed to be our player character, so we’re going to need to remove the automated movement and replace it with player controlled movement.

Leave move(2); where it is, but let’s move turn(2);

for now and create a couple of if statements to house it: if (Greenfoot.iskeydown(“left”))

{turn(-2);} if (Greenfoot.iskeydown(“right”))

{turn(2);}

Greenfoot provides some handy methods for detecting a keyboard press and for assigning button presses to commands. Here we’re looking for the left key being pressed down and turning left by moving negatively on the y-axis, and looking for the right key being pressed down and then turning right by moving positively on the y-axis. If we compile and run our game now, we’ll have a constantly moving ant that we can control by steering left or right. That works quite well as a game mechanic; however, we might want our player to have full control of the player character. Similar to before, we’d need to create a couple of if statements, this time keeping an eye out for the up and down buttons being pressed. Remember positive numbers move right on the x-axis and up on the y-axis, while negative numbers move left on the x-axis and down on the y. Therefore in this case, positive is forward and negative is backward: if (Greenfoot.iskeydown(“down”))

{turn(-2);} if (Greenfoot.iskeydown(“up”))

{turn(2);}

The aim of the game

Perhaps it’s time to introduce some objectives to our game. Because our player character is an ant, let’s add some food for it to gather. Create a new sprite class by right clicking Actor and selecting New Subclass . Next, from the food category select your chosen food type (we’ve gone with Strawberry in this example) and name it appropriat­ely.

Now let’s instruct our ant what to do when it comes across a strawberry. Return to the ant’s code by rightclick­ing and choosing Open Editor , and after our if statements, but still in the act() method , add this code: Actor Strawberry;

Strawberry= get one object at offset (0,0, Strawberry. class);

if (Strawberry != null)

{World world; world = getworld(); world. remove object( strawberry );}

Remember to use the name of your chosen food, and that Java is case sensitive. What we’re doing here is looking to see if our Actor, in this case the ant, comes into contact with a strawberry. The numbers 0,0, are the offset from our ant’s current position, therefore 0,0, means in direct contact. However, we could set an offset of a few pixels away if we so desired. The purpose of the if statement is to say do nothing unless our ant is in contact with a strawberry, hence null. The following code gets the current world by finding the instance of the world class that our game is running, then removes the strawberry from said world.

Compile and play, and marvel in the wonders of a basic search-and-destroy game. We can now move our ant around the game world, and when it comes into contact with food it should eat it. The world resets every time, so when we’ve placed food in the places we’d like it to appear, we need to click Tools and Save World to set things in place. Now every time we press the Reset button our world will resort to this state again.

Now let’s tidy things up a little, making our code more efficient. Rather than having all of this code within the act() method , we should ideally refactor into separate methods for each activity. For instance, the movement could be placed in a method called movement() and the collision detection into one called eating() . In Java we simply copy the format of the method above, so public void movement() and public void eating() would suffice. All the code within the curly brackets {} that follow would be a part of that method. We might want to use the mouse to control our character, instead of the up, down, left and right keys. To do that, we’ll need to make some alteration­s to the movement() method. Replace the if statements with: if( Green foot. mouse moved( null )){ Mouse info mouse= Green foot. get mouse info ();

setlocatio­n (mouse.getx(), mouse.gety());}

Now after saving, compiling and running, our player character will follow the mouse cursor around the world environmen­t. We use null as a fallback in case there’s no new instructio­n, the rest is pretty self explanator­y – we’re getting the X and Y coordinate­s from Mouseinfo and moving our ant there.

Listen up!

Our game is pretty decent so far, it’s playable, at least! However, it’s missing one key element. No game is complete without sound. Since we’ve used Greenfoot’s prefab assets for the sprites and background images, let’s get create and produce our own sound effects. Greenfoot provides a brilliant little tool for recording and importing your own sound effects, directly within the IDE. Under the Tools menu, select Show Sound Recorder. Here we can record to our hearts’ content.

Record a clip for the sound of an ant eating a strawberry (crunch?), play it back, and once we’re happy with it we can give our sound an appropriat­e name and save it (remember those capitals letters). To add the sound to our game we just place the following line of code to the bottom of the if function in our eating() method: Green foot. play sound (“crunch.wav ”);.

We have an environmen­t, our controllab­le player character and some edible objectives. Now, we need to step things up a notch with the introducti­on of some enemy characters. Add a new Actor class with a different type of animal – let’s go with spider this time. The code for our spider will be similar to that of our ant, only it will eat ants instead of strawberri­es. We could allow it to eat the strawberri­es too, bringing in another level of challenge forcing the player to race against the enemy to collect the objectives. Where our spider’s code will differ from that of the ant’s is in the movement() method. Instead of being controlled by the mouse of keyboard, we’ll want our non-player characters to move

independen­tly. We can do this with the help of Greenfoot’s Randomnumb­er method. The following line of code will grab a random number between 0 and 10: turn(greenfoot.getrandomn­umber(10)); . Any higher than that and our spiders will just spin on the spot. Now we’ll need to place some spiders into our game and save the world to ensure they spawn every time we run the game. So starting with the ant: import greenfoot.*; public class Ant extends Actor

{ public void act() {

//move(2); movement(); eating();} public void movement(){ if (Greenfoot.iskeydown(“up”))

{ move(2);

} if (Greenfoot.iskeydown(“down”))

{ move(-2);

} if (Greenfoot.iskeydown(“left”))

{ turn(-2);

} if (Greenfoot.iskeydown(“right”))

{ turn(2); }} public void eating(){

Actor Strawberry;

Strawberry = getoneobje­ctatoffset(0,0,

Strawberry.class); if (Strawberry != null) {

World world; world = getworld(); world.removeobje­ct(strawberry); Greenfoot.playsound(“crunch.wav”);}}} And then use the following code for the spider: import greenfoot.*; public class Spider extends Actor

{ public void act()

To avoid common mistakes in Java, it’s worth always trying to be precise. Java, like most programmin­g languages, is quite picky. Stick to a naming convention and remember that Java is case sensitive. If you capitalise letters in one place, you’ll need to be consistent throughout your code – not just for best practice, but your program won’t compile otherwise.

Also, never forget the semi-colon at the end of a line of code, and be careful not to use the wrong brackets, and to always close brackets that have been opened. On that note, there are three main types of bracket that can be used in Java:

• () Round brackets, otherwise known as parenthese­s, or simply as just brackets. In Java these are used for mathematic­al expression­s and to surround lists and method calls. You’ll noticed we used these after all of our methods, too, to signify no returns.

• [] Square brackets are used for arrays in Java.

• {} Curly brackets, also known as braces or squiggly brackets, are used in Java to wrap around blocks of code, such as methods or the contents of classes. They separate blocks of code to create a pattern of order. A lot of IDES will cascade Java code by the curly brackets. { movement(); eating();} public void movement()

{ move(5);

turn(greenfoot.getrandomn­umber(10));} public void eating()

{ Actor Ant;

Ant = getoneobje­ctatoffset(0,0, Ant.class); if (Ant != null)

{

World world; world = getworld(); world.removeobje­ct(ant); Greenfoot.playsound(“crunch.wav”);}}}

Good luck with your code, and try to adapt and expand your game to improve your code skills. See you next issue for more gaming basics.

 ??  ??
 ??  ?? It might not have been pretty to look at, but it was pretty groundbrea­king at the time!
It might not have been pretty to look at, but it was pretty groundbrea­king at the time!
 ??  ?? OUR EXPERT Calvin Robinson is a former assistant principal and computer science teacher with a degree in computer games design and programmin­g.
OUR EXPERT Calvin Robinson is a former assistant principal and computer science teacher with a degree in computer games design and programmin­g.
 ??  ?? Set up a new Java scenario. Stride is a visual-based programmin­g option.
Set up a new Java scenario. Stride is a visual-based programmin­g option.
 ??  ?? Detecting key presses enables players to control our diminutive character.
Detecting key presses enables players to control our diminutive character.
 ??  ?? Introducin­g edible objectives… who doesn’t like strawberri­es!
Introducin­g edible objectives… who doesn’t like strawberri­es!
 ??  ?? Enemies for the arachnopho­bes among you.
Enemies for the arachnopho­bes among you.
 ??  ?? Testing, one, two, one, two. Sounds good to us!
Testing, one, two, one, two. Sounds good to us!

Newspapers in English

Newspapers from Australia