Tải bản đầy đủ - 0 (trang)
Step 5. Make a List of Technical Requirements for Your Game

Step 5. Make a List of Technical Requirements for Your Game

Tải bản đầy đủ - 0trang

Chapter 3 A PLAN IS WORTH A THOUSAND ASPIRIN



a trade-off in higher system requirements and thus a reduced

audience. This decision must not be made lightly, however. For

instance, more robust AI that makes the game more enjoyable but

taxes the CPU is more justifiable than a bunch of real-time special

effects such as shadows or glows, which look nice but don’t add

any real gameplay value. You and your client’s mileage may vary,

but experience has shown me that the lower you set your technical barrier to entry, the more people will play your game.

Next come the server-side requirements for your game. For

simple games with no data to be saved from session to session,

this is probably as simple as having an HTML page to house your

game’s SWF file. More and more, however, players expect more

robust functionality out of games on the web. The ability to save

their high scores and even maintain a profile for larger games is

very popular, as it gives players bragging rights when they do well

and often affords some level of personalization.

Depending on whether you’re doing the back-end integration (server-side scripts, database work, etc.) or you work with a

team, this list of requirements may look very different. If you work

at a company with a team that already has a database infrastructure in place, your requirements may look something like this:



Methods required



Save score



Parameters—score, number; initials, string; security

hash, string



Returns 0 for success, –1 for error



Load score table



Parameters—size, number



Returns list of initials and scores, highest to lowest

Based on the wireframe example we have created throughout

the previous steps, these two methods (or functions) are all you

will need to post a player’s score and load a table of high scores.

The first method, saving the score, would receive the player’s

score, their initials, and a security hash (which we’ll cover in

depth in Chapter 17). The second method, used when viewing the

high score table, would receive a table size (such as 10 or 20) for

the number of results to return. Regardless of whether your team

works in PHP, .NET, or some other back-end language, this simple

listing will let them know what code they need to expose to Flash

for the game to perform its operations.

If you will be building these scripts yourself and don’t already

have a system in place for doing so, you’ll need to set up a database structure to house all of your game’s data. If you are new to

this area of development but want to learn, I recommend starting with PHP. It is free, it is fast, and it is relatively easy to pick up.

There are also many resources in books and on the web for how

to save data into a database with PHP.



31



32



Chapter 3 A PLAN IS WORTH A THOUSAND ASPIRIN



Techie Note

If you’re already familiar with PHP, I would highly recommend looking into

AMFPHP. It allows you to send binary data in Flash’s native format rather

than name/value strings. Because of this, it allows you to send and receive

typed results (i.e., a number comes back as a number, not a string), and the

chunks of data are much smaller and faster.



Step 6 (Optional). Diagram Your Classes

Using a UML Modeler

UML stands for Unified Modeling Language, and it is the standard for planning complex software through a visual process.

Basically, it involves visually showing the hierarchy of the classes

you intend to create alongside each other, with all the publicly

available properties and methods listed along with what they

accept and return. You may be wondering, “Why would I want to

do that? Why can’t I just get started typing code and build it as I

go?” The answer is simple: A UML diagram takes your whole project into account in a single document. It is much easier to make

changes and correct inconsistencies and confusion in naming

conventions from this bird’s-eye view than when you’ve got a

dozen ActionScript files open and you’re trying to remember the

name of the method you’re trying to call from one to the next. You

can keep the diagram handy as you work, and there are programs

available that will take your completed diagram and turn it into

actual ActionScript class files, complete with all the methods and

properties ready to be used!

Now you’re probably wondering, “Well, if this step is so important and helpful, why do you have it listed at the end as optional?”

There are a couple of reasons for this. One reason is that for very

simple games on a tight timeline, a full-blown UML diagram may

yield low returns on time that could be better spent just knocking out the code. If you’re pretty certain your game will only rely

on a couple of class files, UML is probably overkill. Second, while

many UML tool options exist, including a large number of free

offerings, I have yet to find one that I wholeheartedly recommend

for Flash development. Well, I take that back. The best UML tool

for ActionScript I’ve ever used is Grant Skinner’s gModeler. It is

streamlined especially for this use, it was created in Flash so it

will run on any OS that supports the Flash Player, and it will generate code as well as documentation. Unfortunately, it is several

years old and will only generate up to ActionScript 2 code, leaving

AS3 developers like us in the cold. If you’re still doing work in AS2

(and there’s nothing wrong with that), I highly recommend using

it to model your classes.



Chapter 3 A PLAN IS WORTH A THOUSAND ASPIRIN



Though I haven’t found my equivalent for gModeler for AS3,

I’ve found the free StarUML (http://www.staruml.com) to be a

solid title and fairly straightforward. Also, an Adobe employee has

created a tutorial showing how to generate stub code from your

diagrams much the same way gModeler did. These resources are

available on http://flashgamebook.com.

I know this seems like a lot of steps just to get started if you’re

not used to this level of planning. Trust me, it will not only get

easier and more natural as you figure out what works best for

you, but you will find that fewer surprises pop up down the road.

Now that you have your plan firmly in hand, it’s time to open that

copy of Flash.



A Quick Review of the Planning Steps















One- to two-sentence description

Game screen wireframe and flow

List of game mechanics

List of assets (art, animation, sound, video, and copy)

Technical requirements

UML class diagrams



33



This page intentionally left blank



4

//FTW!

In this chapter, we’ll cover best practices to use when programming in ActionScript 3 (AS3). This includes smart class utilization,

using the event model, error handling, and data structures. We’ll

also cover a number of Flash’s idiosyncrasies that tend to trip up

developers coming to Flash from other languages.



Fair Warning

It’s worth mentioning that this chapter (like the rest of this

book) assumes a familiarity with either ActionScript 1 or 2 or

another programming language. If you have no idea what objects,

variables, or functions are or have never used Flash at all, you will

be lost very quickly. Some familiarity with ActionScript 3 is ideal,

since we’ll also be moving pretty quickly through a wide variety of

topics, but it’s not absolutely necessary. The documentation that

comes with Flash expounds on all of these topics, so if you find

yourself confused or want to learn more, you can check out those

examples. You can also always ask questions on any chapter in

this book at flashgamebook.com. If you’re an experienced AS3

user, be patient—we’ll get through the basics as quickly as possible and move on to the fun stuff!



PART 1

Classes

As we learned in Chapter 1, classes are essentially the blueprints for objects in ActionScript (and many other object-oriented

programming languages). They define the properties that are

inherent to that object as well as the methods that determine how

that object functions on its own and as part of a larger context.

Real-World Flash Game Development

© 2010,

2010 Elsevier Inc. All rights reserved.



35



36



Chapter 4 //FTW!



When you create an object from a class, that object is known as

an instance of that class. Every instance of a class may have different specific values for its properties, but they all share the common architecture, so Flash knows that all instances of a certain

class will behave the same way. In its simplest form, instantiation,

or creation, of an object looks like this in ActionScript:

var myObject:MyClass = new MyClass();



As a standard naming convention, classes should start with a

capital letter and then use InterCaps (or “CamelCase”) from then

on, denoting the start of a word with a capital letter. CamelCase

makes names in code much easier to read—take, for example, the

longest class name currently used in the Flash CS4 code base:

HTMLUncaughtScriptExceptionEvent



While this is something of an extreme example, note that it is

much easier to read than:

htmluncaughtscriptexceptionevent



Packages

A set of classes with categorically similar or related functionality can be grouped together in what are known as packages.

Classes within the same package can reference each other without any special code, while classes in different packages must

import each other with a line of code, similar to the following:

import flash.display.MovieClip;



Note that, in this case, the MovieClip class is inside the display

package, which is part of the larger flash package. The standard

naming convention for packages is all lowercase letters, which

differentiates them from classes visually. Packages are represented in the file system as a series of nested folders. In the previous example, if the MovieClip class were not an included part

of the Flash Player, you could find the MovieClip.as file inside a

folder called display, inside another folder called flash.



Classes as Files

To create a class, you simply open Flash or a text editor like

FlashDevelop and create a basic framework. All AS3 classes must

have this minimal amount of code in order to function:

package flash.display {

public class MovieClip {

}

}



Chapter 4 //FTW!



Note that the names in bold are the custom package and class

names of your choice. All classes need is a class definition wrapped

by a package definition, placed in a folder structure that matches

the package hierarchy. This class won’t do anything, however, so

next we’ll cover adding properties and methods.



Constructors

Every class has a constructor, even if it does nothing and is not

explicitly defined. It is the function, with the same name as the

class, that is called when a new instance of the class is created.

In the case of our last example, even if we leave it out, Flash adds

the following to the class:

package flash.display {

public class MovieClip {

public function MovieClip() {

}

}

}



The constructor allows us to run any initialization code that

the new instance might need, or it can do nothing, depending on

how your class is to be used.



Constants, Variables, and Methods

A class without any data or functionality inside it is not of very

much use, so we can define variables, or properties, of the class

that will store information, methods, or functions that will perform actions. I’m going to assume you already know how to use

variables and methods, either from earlier versions of ActionScript

or another language. Constants are entirely new to AS3 but are not

a complicated concept. Essentially, they are variables that can

only be assigned a value once. When you declare a constant or

variable, it is best to give it a type, which tells Flash which class to

use as the blueprint for that variable. Here are a few examples:

const myInt:int = -3; //WILL ALWAYS BE -3 AND CANNOT BE MODIFIED

var myBoolean:Boolean = true;

var myString:String = “Hello World”;

var myObject:Object = new Object();



Giving a variable a type also saves memory, because Flash

knows the maximum amount of memory it needs to store an

instance of a specific class. If you don’t type a variable, as in the

following example, Flash must reserve a larger amount of memory to accommodate any possible value:

var myMystery:* = “?”;



37



38



Chapter 4 //FTW!



Once you assign a value to an untyped variable, it becomes

typed from then on, so attempts to change its type (like you could

in earlier versions of ActionScript) will result in runtime errors,

such as the following example:

var myMystery:* = “?”;

myMystery = 5; //WILL CAUSE A RUNTIME ERROR



What’s worse, the above example won’t be caught during compilation, so it might get missed until your game is deployed live

for real users. Unless absolutely unavoidable (like an instance

where you simply don’t know what will be assigned to a variable),

always type your variables. You’ll create far fewer headaches

down the road for yourself.

When you define methods, there are similar practices to follow.

It is best practice to define what parameters a method will receive

and what, if anything, it will return:

function myFunction (myParam:String):void {

//COMMANDS HERE

}



In this example, the method accepts a single parameter, myParam, and returns nothing. If you have a case where a method

needs to accept an unknown number of parameters, a slightly

different syntax can be used:

function myFunction (… params):void {

//COMMANDS HERE

}



Here, the single parameter, params, is prefixed by three dots.

This signifies to Flash that it should be treated like an array of values, so getting to each parameter that was passed must be done

through array syntax:

function myFunction (… params):void {

trace(params[0]);

}



It’s important to remember that, when accepting a variable

number of parameters, type checking during compilation will

not catch any attempts to pass invalid data to the method. In this

case, it’s best to do some type of manual checking and generate

errors at runtime. We’ll cover more on errors shortly.

function myFunction (… params):void {

for (var i:int = 0; I < params.length; i++) {

if (!(params[i] is DisplayObject)) {

throw new ArgumentError(“Only DisplayObjects can be used

in myFunction.”);

}

}

}



Chapter 4 //FTW!



The keyword void is used to denote a function that does not

return anything (and will cause an error if it attempts to), and all

other types that variables can use can also be used here. If you

leave off the return value altogether, you can opt to return something or not, depending on some piece of internal logic. However,

as a best practice, a method should always declare what it will

return, as it helps catch errors and maintains consistency.



Getter/Setter Methods

There are two special types of methods you can create when

you want to expose a variable outside its class but want to control how the variable is used. They are known as accessor or getter/

setter methods, and they are called like normal variable assignments but act like functions underneath. You can use them to

make read-only variables or to perform actions on a value before

it is set as a variable. There are a few rules to follow when using

these special methods. Getter methods never accept any parameters and must specify a return type, whereas setter methods may

only have one parameter and never return anything. Let’s look at

a couple of examples in a single script:

package {

public class MyClass {

protected var _maxNameLength:int = 8;

protected var _name:String;

protected var _lives:int = 3;

public function get name():String {

return _name;

}

public function set name(value:String):void {

name = value.substr(0,maxNameLength);

}

public function get lives():int {

return _lives;

}

}

}

//OUTSIDE CLASS

var myInstance:MyClass = new MyClass();

myInstance.name = “CHRISTOPHER”;

trace(myInstance.name); //OUTPUTS “CHRISTOP”;

trace(myInstance.lives); //OUTPUTS 3;

myInstance.lives = 10; //THROWS ERROR



The name getter/setter functions return the protected value

of _name, which would otherwise be inaccessible, and the name

setter function forces any attempts to assign a value to the _name

property to a fixed length of eight characters. The lives getter is

an example of a read-only property—there is no accompanying

setter function. Any attempts to set the value will cause an error.



39



40



Chapter 4 //FTW!



This is very useful when you need to use values inside the class

but also want external classes to be able to read the value.

The standard convention for variable and method names is to

start lowercase and then use CamelCase for all subsequent words

in the name. There is some debate over how to delineate public

variables from protected, private, or internal ones. My preference

is to follow Adobe’s convention, which is to use an underscore

(“_”) at the beginning of the name of any property that is not

expressly public. Doing so allows you to use getter/setter methods like the previous example, where _name was the protected

variable and name was used for the pair of methods. This yields

continuity in your naming and makes your code easier for others

(and yourself) to follow.



Class Identifiers

Classes can use a few different identifiers to determine how

they are exposed to other classes. The four available are:



Public—The public attribute defines that a class can be

accessed or used from anywhere else.



Internal—The internal attribute allows a class to only be

accessed by other classes in the same package; by default,

classes are internal unless specified public, so internal

does not actually have to be used.



Dynamic—If a class is dynamic, it can have properties

and methods added to it at runtime; by default, classes

are static and can only use the properties and methods

defined inside themselves.



Final—If a class is final, it cannot be extended by another

class (more on this shortly when we cover inheritance); by

default, classes can be extended and are not final.

All of these identifiers can be used with each other, except

that public cannot be used with internal. Similarly, variables and

methods can have their own set of identifiers used to define how

they are exposed outside the class:



Public—Like the class attribute, this denotes that a variable or method can be accessed from anywhere, including

outside the class.



Internal—Also similar to classes, this denotes that a variable or method can only be accessed from inside its

package.



Private—The private attribute prevents a variable or

method from being accessed outside its individual class.



Protected—A protected attribute is pretty much like private, except that protected variables and methods can also

be accessed by classes that extend the current class (more

on inheritance shortly).



Chapter 4 //FTW!



Static—If a method or variable is static, it is part of the

class, not instances of the class, meaning that there is only

ever one value or functionality defined, and it is accessed

via the class name rather than an instance (e.g., MovieClip.

staticVar rather than myMovieClip.staticVar); it is important to note that static properties and methods are not

inherited by subclasses.

The first four attributes in this list cannot be used with each

other, as they would conflict, but static can be used in combination with any one of them.





Inheritance and Polymorphism

When you need to create a class that has the same functionality

as another class but requires some additional properties or methods, a good option to save time and coding is to extend the first

class to a new class, known as a subclass. All public and protected

methods and variables that are not static will be available to the

new class. To clarify, any static properties of the parent, or superclass, must be prefaced with the class name (as in the example

below). Additionally, any internal methods or variables will be available to the subclass if it is in the same package as its superclass. To

illustrate, let’s look at an example:

package {

public class SuperClass {

static public var className:String = “SuperClass”;

}

}

package {

public class SubClass extends SuperClass {

public function SubClass() {

trace(SuperClass.className); //OUTPUTS “SuperClass”

trace(className); //THROWS ERROR

}

}

}

//FROM OUTSIDE EITHER CLASS

trace(SuperClass.className); //OUTPUTS “SuperClass”

trace(SubClass.className); //THROWS ERROR



Occasionally, you’ll need to change the functionality of a

method in a subclass from the way it behaves in the superclass.

This change in functionality through inheritance is known as

polymorphism. You can do this using the override keyword before

the beginning of the method, albeit with a number of caveats:



Only methods may be overridden, no properties.



Only public, protected, and internal methods may be

overridden.



41



Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Step 5. Make a List of Technical Requirements for Your Game

Tải bản đầy đủ ngay(0 tr)

×