Read Foundation Game Design with ActionScript 3.0, Second Edition Online
Authors: Rex van der Spuy
This is a long program but notice that the bulk of the code has nothing to do with the mechanics of the game. About 70% of it has to do with setting up, displaying, and managing the text fields and buttons. In a big game project you'll find that most of your code will be about displaying graphics and managing the user interface, just like in this game.
Part of the reason why it's important to modularize your code using bite-sized methods is so that you can separate the programming of the visual elements from the programming of the game logic. Doing so makes the game much easier to write because when you finish programming one method, you don't need to look at it again. You can concentrate on the code in another method.
Still, in a complex game with hundreds of different graphic elements, this approach will only take you so far. You're going to need to learn how to modularize your code even further so that you can completely bury code that you no longer need to work on. In
Chapter 7
you'll be looking at how to make games using multiple classes, which will partially solve the problem. The ultimate solution is to use a more advanced approach using a programming
design pattern
called the Model View Controller (MVC). It's beyond the
scope of this book to cover the MVC, but you can find out all about it in the sequel to this book,
Advanced Game Design with Flash
.
While you're still learning, however, modularizing your code using methods will take you quite far, and you'll learn a lot in the process. Here are some ideas for making your games and programs easier to manage:
You'll see all these techniques at work in the code in the chapters ahead.
This is the first complete game in this book. But is it really done?
Game design is a funny thing. Games, even complex ones, are never really finished. Designers just stop working on them when they seem to play well enough that no one complains. There are usually many deep layers of complexity or added functionality that
could
be added to games if the designer had enough time, patience, and imagination to do so. Patience and imagination are things game designers seem to have in endless supply. It's usually
time
that throws the spanner in the works.
There's quite a bit more that you could add to this game. Here are some ideas.
Display a button at the end of the game that allows the player to play again. I'm not going to explain how to do this because you already know how! You know how to make buttons, set object properties, and create and call methods. By creating a Play again button on your own, you're going to practice all the skills you've learned over the last four chapters: everything from designing the graphics to writing the code. You'll also run into some problems you never imagined existed, eventually solve them, and feel like you're walking on clouds when everything is finally working properly.
When you're done, your number guessing game might look something like
Figure 4-36
.
Figure 4-36.
Create a Play again button to restart the game.
Here are a few hints to help you on the way:
endGame
method should enable the Play again button.startGame
method in the play again button's CLICK event handlerIf you get terminally stuck, you'll find the finished game with a Play again button in the PlayAgain folder in this chapter's source files.
Good luck!
You set the game up to allow ten guesses, but some players might not have the patience to remember what their previous guesses were. You can add another text field that displays all their previous guesses for them and adds the new guess when they make it.
To do this, you'll need a new text field, perhaps calledguessHistory
. You can create a new string variable calledpreviousGuesses
that stores all the guesses as a string of text with each number separated by a blank space. Whenever the player makes a new guess, you can add it to thepreviousGuesses
variable and then update theguessHistory
text field. Here's a sample of what the core of this code will look like:
previousGuesses += currentGuess + " ";
guessHistory.text = previousGuesses;
This line of code will work well in theplayGame
method. Can you see how the code in the first directive would separate each number with a blank space?
A hangman-style visual display of how well (or poorly!) the player is doing is an interesting enhancement. You could create ten images showing ten different hangman states. Use the visible property to selectively display or hide each state depending on how the game is going. Each state can incrementally show the player how close they are to impeding peril, like the addition of limbs to the chalk figure in game of Hangman.
A more advanced project that's fun to try is to change the game so that the program needs to guess a number that
you're
thinking of. This will be a completely new program, but you currently have all the skills you need to make it work.
Want to give it a try? Here's a hint: to get this game working, you'll need to use a
division operator
. You've already seen the multiplication operator.
*
You used the multiplication operator to multiply the random number by 100. The division operator looks like this:
/
It's a simple forward slash. You can use it in any directive to divide two numbers.
100 / 2
This example gives a result of 50. You can then assign this calculation to variable in a directive. Here's an example:
computersGuess = (100 / 2);
Can you see where I'm going with this? I'm not going to spoil your fun of figuring out the rest! This will be a difficult project for you, but you can do it. And what you'll learn along the way will give you an invaluable insight into your own developing skills and style as a game programmer.
If you want the fonts in your games to display correctly on computers other than yours, you'll need to
embed
them. An embedded font is stored inside the SWF file and doesn't require the person who's playing the game to have that same font installed on his or her computer. Here are the steps you need to follow to embed a font:
public class EmbeddedFonts extends Sprite
{
[Embed
(
source="../fonts/Optima.ttc",
embedAsCFF="false",
fontName="embeddedFont",
fontWeight="normal",
advancedAntiAliasing="true",
mimeType="application/x-font"
)
]
private var EmbeddedFontClass:Class;
The most important thing about this code is that the source parameter needs to provide the exact path to the font file in your project directory.
format
object's font property to “embeddedFont”. This should match the name you provided in thefontName
parameter in your code.format.size = 32;
format.color = 0x000000;
format.font = "embeddedFont"
embedFonts
property to true.output.embedFonts = true;
Your published SWF will now display the font correctly on any computer.
In the chapter's source files you'll find a folder called EmbeddedFonts with a working example of this system. It displays a line of text using an embedded font. Here's the entireEmbeddedFont
class:
package
{
import flash.display.Sprite;
import flash.text.*;
public class EmbeddedFonts extends Sprite
{
[Embed
(
source = "../fonts/Optima.ttc",
embedAsCFF = "false",
fontName = "embeddedFont",
fontWeight = "normal",
advancedAntiAliasing = "true",
mimeType = "application/x-font"
)
]
private var EmbeddedFontClass:Class;
//Create the format and text field objects
public var format:TextFormat = new TextFormat();
public var output:TextField = new TextField();
public function EmbeddedFonts()
{
//1. Configure the format
format.size = 32;
format.color = 0x000000;
//The name of the font should match
//the "name" parameter in the Embed tag
format.font = "embeddedFont";
//2. Configure the text field
output.defaultTextFormat = format;
output.embedFonts = true;
output.autoSize = TextFieldAutoSize.LEFT;
output.antiAliasType = flash.text.AntiAliasType.ADVANCED;
output.border = false;
output.defaultTextFormat = format;
output.text = "The text you want to display.";
stage.addChild(output);
output.x = 50;
output.y = 175;
}
}
}
Embedded fonts can sometimes behave in quirky ways, and this often depends on the specific font file you're trying to embed. If you have any problems, first try removing this line from the Embed metatag:
embedAsCFF = "false",
This often does the trick.
The number guessing game that you looked at in this chapter is extremely important for a few reasons:
Before you continue in this book, take a short break to create a game of your own based on the techniques covered so far. There's no better way to learn than by trying things out in your own way, and it will give you a greater appreciation for some of the more advanced techniques you'll be looking at in the chapters ahead.
In
Chapter 5
, you'll take a detailed look at how to control objects on the stage with the keyboard. It will be the stepping stone you need to progress from designing
games
to designing
video games
.
One of the first things your games should do is allow game players to move an object around the stage. A game object could be moved with either the mouse or the keyboard. In this chapter, you'll look at techniques for controlling an object with the keyboard.
This chapter covers the following topics:
One of the most basic things a game should do is allow players to control a game character with a keyboard. It's not hard to do. It's a technique that makes use of two of AS3.0's built-in classes: theKeyboardEvent
class and theKeyboard
class. To use them, you simply import them into the top of your program, along with your other imported classes.
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
You used both of these classes in
Chapter 4
to allow players to enter text into the input text field by pressing the Enter key on the keyboard. TheKeyboardEvent
andKeyboard
classes contain methods and properties that you can use to help your players interact with your games using the keyboard. And, like theMouseEvent
class properties, you'll be using all these new methods and properties with your eyes closed in no time at all.
There are two ways to control an object with the keyboard: the right way and the wrong way. Let's look at the wrong way of doing it first.
Why would you learn the wrong way? Well, the nice thing about doing player keyboard control incorrectly is that it's very straightforward and easy to understand. And, oh yeah, it kind of works, too. But even if you never use it to control a player character in one of your games, you'll find endless other uses for it as a general technique for figuring out which keys your players are pressing on the keyboard. It's also the basis for understanding the right way to do keyboard control, which adds a few extra layers of flexibility and polish to the same underlying system. If you understand how the wrong way works first, you'll be better able to understand and appreciate the right way to do things. But don't worry, I'll take things a step at a time. You'll be surprised at how simple the process is when you put all the pieces together.
Let's write a simple program that demonstrates this.
Figure 5-1.
Copy the character.png file into the images folder.
package
{
import flash.net.URLRequest;
import flash.display.Loader;
import flash.display.Sprite;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
[SWF(width="550", height="400",
backgroundColor="#FFFFFF", frameRate="60")]
public class SimpleKeyboardControl extends Sprite
{
//Create the game character objects
public var characterURL:URLRequest
= new URLRequest("../images/character.png");
public var characterImage:Loader = new Loader();
public var character:Sprite = new Sprite();
public function SimpleKeyboardControl()
{
//Load the image and add the character to the stage
characterImage.load(characterURL);
character.addChild(characterImage);
stage.addChild(character);
character.x = 225;
character.y = 150;
//Add a KeyboardEvent listener
stage.addEventListener
(KeyboardEvent.KEY_DOWN, keyDownHandler);
}
public function keyDownHandler(event:KeyboardEvent):void
{
if (event.keyCode == Keyboard.LEFT)
{
character.x -= 10;
}
else if (event.keyCode == Keyboard.RIGHT)
{
character.x += 10;
}
else if (event.keyCode == Keyboard.DOWN)
{
character.y += 10;
}
else if (event.keyCode == Keyboard.UP)
{
character.y -= 10;
}
}
}
}
Figure 5-2.
Move the game character around the stage with the keyboard arrow keys.
I'm sure you noticed some obvious problems with this player character control scheme already, but before I show you the solutions, let's have a quick look at how it works. The first thing you had to do was import theKeyboardEvent
andKeyboard
classes into the program.
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
TheKeyboard
class's primary job is to make it easier to figure out which keys the player is pressing. TheKeyboardEvent
class allows you to add an event listener to the stage to listen for key presses. That's exactly what this bit of code in the constructor method does:
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
This is the same event listener you used in
Chapter 4
, and it works in the same way. Its job is to detect when any keys are pressed on the keyboard. It calls thekeyDownHandler
, whose job is to process this event.
public function keyDownHandler(event:KeyboardEvent):void
{
if (event.keyCode == Keyboard.LEFT)
{
character.x -= 10;
}
else if (event.keyCode == Keyboard.RIGHT)
{
character.x += 10;
}
else if (event.keyCode == Keyboard.DOWN)
{
character.y += 10;
}
else if (event.keyCode == Keyboard.UP)
{
character.y -= 10;
}
}
As you learned in
Chapter 4
,Keyboard.LEFT
,Keyboard.RIGHT
,Keyboard.DOWN
, andKeyboard.UP
represent numbers that AS3.0 links to keys on the keyboard. These numbers are called key codes.
The key codes that AS3.0 uses are based on ASCII, which is a fixed standard for interpreting numbers as characters. For example, the ASCII number 65 refers to the uppercase letter A. However, different operating systems don't map these codes to the keyboard keys in exactly the same way. If you design and test a game using key codes on a Windows computer and then run the SWF on another operating system such as OS X, the key codes that you used might not match OS X's keyboard mapping. For this reason, it's preferable to use theKeyboard
class's built-in key properties (such as LEFT and RIGHT,) instead of the actual key code numbers.
If you need to use a key that isn't represented by these properties, you have to use a key code number. Make sure that you test these key codes carefully on each operating system your game will run on to ensure that it's mapped to the correct keys on every one.
If you're building a game using Flash Professional software, some keys may not work while you're building and testing the game. Flash Professional reserves some keys for shortcuts (for example, Ctrl and S to save a file). So if you used any of these keys or key combinations in your game, you need to hold down Shift while testing the keys to override Flash Professional's own use of them. The keys will work fine in the published SWF.
Very simply, thekeyPressHandler
contains an if/else statement that figures out which key is being pressed and then moves the character left, right, down, or up by adding or subtracting 10 pixels from its x or y positions.
That's easy enough, but why is it working so badly? When you tested the program, you might have noticed a few big problems:
These problems are due to your computer keyboard's
key buffer
. When you press a key on the keyboard, the keyboard tells the computer that the key has been pressed down only once; it doesn't know if the key is being
held down.
The computer's operating system has a key repeat feature built into it that resends the KEY_DOWN event at regular intervals. The key repeat is needed for word processors, for example, so that you can hold down a key to repeat a character on the screen. You don't have any control over how the key repeat runs, and the result with a Flash game is the jittery movement you see on the stage.
To solve this problem, you need to work around the key buffer so the keys don't directly move the object. You can use the keys to determine the object's direction and speed, but you need to find another way to actually move the object.
Now that you know how AS3.0 can find out which keys you're pressing, you can use this same basic system to refine the keyboard control program.
There's a lot of new stuff here, but don't panic! I'll break everything down step by step once you have the program running to show you exactly how it works. But for now, here's a quick summary of what you need to do:
Event
class so that you can use its ENTER_FRAME property.vx
andvy
. These variables will store the vertical and horizontal velocities of the object.keyDownHandler
so that it no longer changes the position of the character. Instead, it updates thevx
andvy
variables with the speed and direction that the object should move in.keyUpHandler
. Its job is to detect when the arrow keys are released. When they are, it sets the character's speed to 0.enterFrameHandler
that uses thevx
andvy
variables to actually move the character.