Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Beginning ActionScript 2.0 2006

.pdf
Скачиваний:
101
Добавлен:
17.08.2013
Размер:
12.47 Mб
Скачать

Chapter 5

The first step performed within the for loop is to create empty movie clips:

// Create a movie clip baseMovieClip.createEmptyMovieClip(“buttonClip” + i, ;

baseMovieClip.getNextHighestDepth()); tempMovieClipHolder = baseMovieClip[“buttonClip” + i];

Next, an ID is assigned to the movie clip. The ID can take any form, but it’s convenient to use the iterator i:

// Assign an ID to a timeline variable tied to the button tempMovieClipHolder.buttonID = i;

The movie clip is then filled with something so that it is visible:

//Draw something inside the button so it can be seen and clicked on tempMovieClipHolder.lineStyle(1, 0x333333); tempMovieClipHolder.beginFill(0x6666AA); tempMovieClipHolder.moveTo(0, 0);

tempMovieClipHolder.lineTo(50, 0); tempMovieClipHolder.lineTo(50, 25); tempMovieClipHolder.lineTo(0, 25); tempMovieClipHolder.lineTo(0, 0);

//Position the button

tempMovieClipHolder._y = 10; tempMovieClipHolder._x = i * 60 + 10;

The clickable area depends on the contents of the clip, so an empty button is un-clickable.

The final step in the loop is to create a click handler for the movie clip. An anonymous function is created to retrieve the variable assigned to the movie clip and pass it along to a handler function:

//Make the button clickable. Pass along the ID assigned to the

//button’s timeline

tempMovieClipHolder.onRelease = function()

{

handleButtonClick(this.buttonID);

}

The this keyword refers to the parent object, which is the movie clip holding this particular onRelease handler. You could have assigned the handler function directly to the onRelease event property, but it isn’t possible to retrieve the ID from within that function:

tempMovieClipHolder.onRelease = handleButtonClick; function handleButtonClick()

{

trace(“Clicked on button number: “+this.buttonID);

}

128

Getting Started with Coding

Finally, the handler function is declared:

function handleButtonClick(buttonID:Number)

{

trace(“Clicked on button number: “ + buttonID);

}

Creating Your Own Functions

Here are a number of best practices to keep in mind when you create custom functions (as you will in Chapter 27):

Strongly type function arguments.

Avoid hard-coded movie clip references.

Declare return values.

Avoid oversized functions.

Avoid entanglement.

Avoid duplication.

These guiding principles are examined in the following sections.

Strongly Typing Function Arguments

Chapter 2 discussed the advantages of strong typing, and those advantages apply to function arguments as well as to the variables that you declare. In fact, for strong typing to really be useful, all variables, including function arguments, should be strongly typed. This guideline is easy to adhere to, but needs to be followed consistently to take advantage of compile-time type checking and code completion. The following code shows a function with strongly typed arguments:

function createButton(baseMovieClip:MovieClip, labelText:String):Void

{

// Function contents

}

On rare occasions, you might not know exactly what data type will be passed in. If that’s the case, declare the type as Object rather than omitting the type declaration. Here’s an example:

function deleteObject(objectToDelete:Object):Void

{

if (typeof(objectToDelete) == “movieclip”)

{

objectToDelete.stop();

objectToDelete.removeMovieClip();

}

else

{

129

Chapter 5

delete objectToDelete;

}

}

Avoiding Hard-Coded Movie Clip References

Avoid hard-coding movie clip references to function code. If a function contains hard-coded movie clip references, it becomes harder to reuse the function elsewhere. Pass a base movie clip reference as a parameter. The following snippet shows a function with a hard-coded movie clip reference:

function createButton(instanceName:String):Void

{

_level0.baseMovieClip.createEmptyMovieClip(instanceName, ;

_level0.baseMovieClip.getNextHighestDepth());

}

createButton(“button1”, “Button One”);

This code can be reworked a bit to make it more generic and therefore easier to reuse:

function createButton(baseClip:MovieClip, instanceName:String):Void

{

baseClip.createEmptyMovieClip(instanceName, baseClip.getNextHighestDepth());

}

createButton(_level0.baseMovieClip, “button1”, “Button One”);

Declaring Return Values

When declaring a function that should return a value, make sure that the return type is declared. If no value is to be returned, declare the special type Void. Here’s an example:

function setName(nameString:String):Void

{

myName = nameString;

}

function getName():String

{

return myName;

}

Make sure that a function that is to return a value will return something every time, including in error cases. The following example shows you both non-returning and returning code:

// This function will not always return a value function getCameraMake(cameraModel:String):String

{

if (cameraModel == “D70”)

{

return “Nikon”;

}

else if (cameraModel == “10D”)

{

return “Canon”;

130

Getting Started with Coding

}

}

// This function contains a default statement function getCameraMake(cameraModel:String):String

{

if (cameraModel == “D70”)

{

return “Nikon”;

}

else if (cameraModel == “10D”)

{

return “Canon”;

}

return “<Unknown>”;

}

Remember that execution of a function terminates as soon as a return statement is reached. By putting a default return statement on the last line of the function, you’re assured that if the function manages to get as far as the last line, some value will be returned.

Avoiding Oversized Functions

Large functions generally mean that they’re doing too many things. A function should generally have a single focus to it, and a task should take no more than 20 to 30 lines of code. If your functions are consistently more than one or two screens, take a closer look to see if chunks of code can be pulled into their own functions.

Avoiding Entanglement

To entangle is to twist together into a confusing mass. There is nothing better to describe the worst case of code entanglement. When that definition is applied to code, it refers to the mixing together of code with different purposes. Consider an action game in which the code needs to respond to the keyboard. Here’s an example of a key detect function:

var keyListener:Object = new Object(); keyListener.onKeyDown = function()

{

switch (Key.getCode())

{

case Key.SPACE : gunSound.start();

spaceship.fireEffect.gotoAndPlay(1); ammoLeft -= 10;

spaceshipVelocity -= 2; break;

case Key.LEFT :

// Code to move ship left break;

case Key.UP :

// Code to move ship up break;

case Key.RIGHT :

// Code to move ship right

131

Chapter 5

break; case Key.DOWN :

// Code to move ship down break;

}

};

Key.addListener(keyListener);

Two main entanglement issues exist within this routine. First, it contains code that has nothing to do with key detection. Second, within the code to detect the pressing of the space bar, there is direct access to other elements of the project. The effect of these issues is that if you want something else to trigger this code, say through the addition of a joystick, the code would have to be duplicated. It also means that if one element of the game is to change, there is no single place where you can make the changes. The following version is less entangled:

var keyListener:Object = new Object(); keyListener.onKeyDown = function()

{

switch (Key.getCode())

{

case Key.SPACE: handleFireKey(); break;

case Key.LEFT: handleMove(“left”); break;

case Key.UP: handleMove(“up”); break;

case Key.RIGHT: handleMove(“right”); break;

case Key.DOWN: handleMove(“down”); break;

}

};

Key.addListener(keyListener);

function handleFireKey():Void

{

playSound(“gun”);

triggerFireAnimation(); adjustVelocity(-2); adjustAmmo(-10);

}

function handleMove(moveDirection:String):Void

{

// Move code goes here

}

The process of adapting functions is called refactoring, and involves the rewriting of code while retaining existing functionality.

132

Getting Started with Coding

Avoiding Duplication

Functions are good at making repetitive tasks easier. If you go through your code, and see a number of places where the same code appears, it’s a good idea to place that code in its own function. If the functionality needs to change later on, it can be modified in one place to take effect throughout the project.

Try It Out

Refactor Problematic Code

This example shows you a bit of the process of reworking code to improve its style and organization. You split code into functions, and then rework those functions to improve their versatility and organization.

1.Create a new Macromedia Flash document by selecting File New and choosing Flash Document from the New Document panel.

2.Click the first frame in the timeline, open the Actions panel (Window Development Panels Actions), and type in the following ActionScript code:

#include “tryItOut_refactor.as”

3.Select File Save As, name the file tryItOut_refactor.fla, choose an appropriate directory, and save it.

4.Create a new script file by selecting File New and choosing ActionScript File from the New Document panel.

5.Select File Save As and ensure it is showing the same directory containing the Flash project file. Give the file the name tryItOut_refactor.as and save it.

6.Enter the following code into the new ActionScript file:

//Create play button

_level0.createEmptyMovieClip(“playButton”, 1); playButton.onRelease = function()

{

trace(“Pressed play”); presentationArea.play();

}

playButton._x = 10; playButton._y = 10; playButton.beginFill(0xAAAAFF);

playButton.lineStyle(1, 0x333333); playButton.moveTo(0, 0); playButton.lineTo(50, 0); playButton.lineTo(50, 20); playButton.lineTo(0, 20); playButton.lineTo(0, 0);

playButton.createTextField(“labelField”, 1, 4, 4, 50, 15); playButton.labelField.text = “Play”;

// Create stop button _level0.createEmptyMovieClip(“stopButton”, 2); stopButton.onRelease = function()

{

trace(“Pressed stop”); presentationArea.stop();

133

Chapter 5

}

stopButton._x = 70; stopButton._y = 10; stopButton.beginFill(0xAAAAFF);

stopButton.lineStyle(1, 0x333333); stopButton.moveTo(0, 0); stopButton.lineTo(50, 0); stopButton.lineTo(50, 20); stopButton.lineTo(0, 20); stopButton.lineTo(0, 0);

stopButton.createTextField(“labelField”, 1, 4, 4, 50, 15); stopButton.labelField.text = “Stop”;

// Create presentation area, and load a movie clip into it _level0.createEmptyMovieClip(“presentationArea”, 3); presentationArea._x = 10;

presentationArea._y = 40; presentationArea.loadMovie(“http://www.nathanderksen.com/book/;

tryItOut_refactorAnimation.swf”);

7.Save the file (File Save), return to the project file, and select Control Test Movie.

8.Remove the contents of each onRelease event handler, and place it into their own functions, called invokePlay() and invokeStop(). Place a call to both of these functions from within the respective onRelease event handler:

function invokePlay():Void

{

trace(“Pressed play”); presentationArea.play();

}

function invokeStop():Void

{

trace(“Pressed stop”); presentationArea.stop();

}

playButton.onRelease = function()

{

invokePlay();

}

stopButton.onRelease = function()

{

invokeStop();

}

9.Create a new function called setupMovie(), and move the last four lines of code inside the function:

function setupMovie():Void

{

// Create presentation area, and load a movie clip into it _level0.createEmptyMovieClip(“presentationArea”, 3);

134

Getting Started with Coding

presentationArea._x = 10; presentationArea._y = 40;

presentationArea.loadMovie(“http://www.nathanderksen.com/book/; tryItOut_refactorAnimation.swf”);

}

10.Create a new function called createButton(). Give it five input arguments: buttonName of type String, buttonLabel of type String, xPos of type Number, yPos of type Number, and callback of type Function.

11.Copy the code from the // Create play button comment until just before the // Create stop button comment, and paste it in the createButton() function.

12.Modify the contents of createButton() to look like the following code:

function createButton(buttonName:String, buttonLabel:String, ; xPos:Number, yPos:Number, callback:Function):Void

{

var buttonHandle:MovieClip;

_level0.createEmptyMovieClip(buttonName, _level0.getNextHighestDepth()); buttonHandle = _level0[buttonName];

buttonHandle.onRelease = function()

{

callback();

}

buttonHandle._x = xPos;

buttonHandle._y = yPos; buttonHandle.beginFill(0xAAAAFF); buttonHandle.lineStyle(1, 0x333333); buttonHandle.moveTo(0, 0); buttonHandle.lineTo(50, 0); buttonHandle.lineTo(50, 20); buttonHandle.lineTo(0, 20); buttonHandle.lineTo(0, 0);

buttonHandle.createTextField(“labelField”, 1, 4, 4, 50, 15); buttonHandle.labelField.text = buttonLabel;

}

13.Remove the code that creates the play button and the pause button from the top of the code listing.

14.Add two calls to the create button function, and one call to setupMovie():

createButton(“playButton”, “Play”, 10, 10, invokePlay); createButton(“stopButton”, “Stop”, 70, 10, invokeStop); setupMovie();

15.Your code should now look something like this:

function invokePlay():Void

{

trace(“Pressed play”); presentationArea.play();

}

function invokeStop():Void

{

135

Chapter 5

trace(“Pressed stop”); presentationArea.stop();

}

function setupMovie():Void

{

// Create presentation area, and load a movie clip into it _level0.createEmptyMovieClip(“presentationArea”, 3); presentationArea._x = 10;

presentationArea._y = 40; presentationArea.loadMovie(“http://www.nathanderksen.com/book/;

tryItOut_refactorAnimation.swf”);

}

function createButton(buttonName:String, buttonLabel:String, ; xPos:Number, yPos:Number, callback:Function):Void

{

var buttonHandle:MovieClip;

_level0.createEmptyMovieClip(buttonName, _level0.getNextHighestDepth()); buttonHandle = _level0[buttonName];

buttonHandle.onRelease = function()

{

callback();

}

buttonHandle._x = xPos; buttonHandle._y = yPos; buttonHandle.beginFill(0xAAAAFF); buttonHandle.lineStyle(1, 0x333333); buttonHandle.moveTo(0, 0); buttonHandle.lineTo(50, 0); buttonHandle.lineTo(50, 20); buttonHandle.lineTo(0, 20); buttonHandle.lineTo(0, 0);

buttonHandle.createTextField(“labelField”, 1, 4, 4, 50, 15); buttonHandle.labelField.text = buttonLabel;

}

createButton(“playButton”, “Play”, 10, 10, invokePlay); createButton(“stopButton”, “Stop”, 70, 10, invokeStop); setupMovie();

16.Save the file, return to the Flash project file, and select Control Test Movie. The project should work identically as before.

17.You’ve done a significant amount of refactoring, and it’s a definite improvement. You can still do better, though. Create a new function called drawBox() and give it five arguments: targetMovieClip of type MovieClip, as well as boxWidth, boxHeight, boxColor, and lineColor, each of type Number. Copy the code in the createButton() function from the line calling beginFill() to the last lineTo() call, and paste it into the drawBox() function. Modify the code to match the following:

function drawBox(targetMovieClip:MovieClip, boxWidth:Number, ; boxHeight:Number, boxColor:Number, lineColor:Number):Void

{

136

Getting Started with Coding

targetMovieClip.beginFill(boxColor); targetMovieClip.lineStyle(1, lineColor); targetMovieClip.moveTo(0, 0); targetMovieClip.lineTo(boxWidth, 0);

targetMovieClip.lineTo(boxWidth, boxHeight); targetMovieClip.lineTo(0, boxHeight); targetMovieClip.lineTo(0, 0);

}

18.Replace the code in the createButton() function from the line calling beginFill() to the last lineTo() call with the following line:

drawBox(buttonHandle, 50, 20, 0xAAAAFF, 0x333333);

19.The final code listing should look like this:

function invokePlay():Void

{

trace(“Pressed play”); presentationArea.play();

}

function invokeStop():Void

{

trace(“Pressed stop”); presentationArea.stop();

}

function setupMovie():Void

{

// Create presentation area, and load a movie clip into it _level0.createEmptyMovieClip(“presentationArea”, 3); presentationArea._x = 10;

presentationArea._y = 40; presentationArea.loadMovie(“http://www.nathanderksen.com/book/;

tryItOut_refactorAnimation.swf”);

}

function createButton(buttonName:String, buttonLabel:String, ; xPos:Number, yPos:Number, callback:Function):Void

{

var buttonHandle:MovieClip;

_level0.createEmptyMovieClip(buttonName, _level0.getNextHighestDepth()); buttonHandle = _level0[buttonName];

buttonHandle.onRelease = function()

{

callback();

}

buttonHandle._x = xPos; buttonHandle._y = yPos;

drawBox(buttonHandle, 50, 20, 0xAAAAFF, 0x333333); buttonHandle.createTextField(“labelField”, 1, 4, 4, 50, 15); buttonHandle.labelField.text = buttonLabel;

}

137