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

Beginning ActionScript 2.0 2006

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

Chapter 12

9.Set Breakpoint button: Sets a breakpoint at the current point of execution.

10.Clear All Breakpoints button: Clears all breakpoints that have been set in the entire project, not

just for the code currently shown in the code preview pane.

11.Step Over button: Causes the function currently highlighted by the progress arrow to run, and then advances the progress arrow to the next line of code. It does not cause the progress arrow to enter that function.

12.Step In button: Causes the progress arrow to proceed into any custom function currently highlighted by the progress arrow, starting at the first line of code for that function. If you want to examine each line of code in each function and nested function, simply click this button repeatedly.

13.Step Out button: Causes the progress arrow to continue to the next line of code in the calling function, skipping any remaining code in the current function.

14.Code Selector: If code is located in multiple places on the timeline, or within multiple included files, this drop-down enables you to navigate between the different timelines or files.

15.Code Preview pane: Shows the currently running code in its context. It does not allow you to edit any code at runtime.

16.Breakpoint and progress area: The gray area on the left is used for setting or removing breakpoints, and for showing the line to be executed next. The Set Breakpoint button (number 9 in this list) sets a breakpoint only for the currently running line. This area allows breakpoints to be set and removed for any line of code by clicking to the left of the number of the code line of interest. Breakpoints cannot be set for lines containing function declarations, opening or closing brackets for a function, or blank lines. The gray area on the left is also used to show the progress of code execution. A yellow arrow appears to the left of the line number for the line of code that will be executed next.

Ready to try out the debugger?

Try It Out

Working with the Debugger

This exercise gives you some practice with using the debugger.

1.Create a new Macromedia Flash document.

2.Select Modify Document and change the stage dimensions to be 400 pixels wide by 400 pixels high.

3.Click the first frame in the timeline, open the Actions panel (Window Actions), and enter in the following ActionScript code:

init();

function init()

{

var stageSize:Number = Stage.height; var squareSize:Number = stageSize / 8; var currentX:Number;

308

Debugging Debugged

var currentY:Number;

this.createEmptyMovieClip(“checkerBoardClip”, this.getNextHighestDepth());

for (var i:Number = 0; i < 8; i++)

{

currentY = i * squareSize;

for (var j:Number = 0; j < 8; j++)

{

currentX = j * squareSize; if ((i + j) % 2 == 0)

{

drawSquare(checkerBoardClip, currentX, currentY, ; squareSize, 0x000000);

}

}

}

}

function drawSquare(sourceClip:MovieClip, x:Number, y:Number, ; size:Number, color:Number):Void

{

sourceClip.beginFill(color, 100); sourceClip.moveTo(x, y); sourceClip.lineTo(x, y + size); sourceClip.lineTo(x + size, y + size); sourceClip.lineTo(x + size, y); sourceClip.lineTo(x, y);

}

4.Select File Save As, name the file tryItOut_debuggerPractice.fla, and save it in an appropriate directory.

5.Click just to the left of the line number of the first line in the init() function to set a breakpoint. The breakpoint marked should appear next to the first bold line in the preceding code.

6.Click just to the left of the line number of the first line in the drawSquare() function to set a breakpoint. The breakpoint marked should appear next to the second bold line in the preceding code.

7.Choose Control Debug Movie.

8.Click the Locals tab. Click the Play button in the debug panel.

9.Click the Step Over button repeatedly, observing the changes in the local variables.

10.Click the Step Into button repeatedly, making a couple of passes through the entire code. Observe the changes in the local variables and the call stack. Also observe the drawing on the screen as it steps through the drawSquare() function.

11.Select the checkerBoardClip movie clip in the movie clip browser. Select the Properties tab. Click the Play button repeatedly, watching the periodic change in the _height property.

12.If the progress arrow is not already within the drawSquare() function, click the Play button so that the arrow is shown on top of the second breakpoint icon. Click the Step Out button to continue to the next line of code in the calling function.

13.Close the debug panel.

309

Chapter 12

How It Works

Breakpoints are used to stop execution when the marked line of code is about to be executed. The Step Over, Step In, and Step Out buttons are used to offer fine control over the progress of code execution. The Play button is used to continue execution until the next breakpoint. The Step Over button runs the line of code with the progress arrow next to it, but does not attempt to stop at any of the lines of code within that function. The Step In button proceeds to the first line of code within the function marked by the progress arrow, if possible. The Step Out button proceeds to the line of code in the parent function that immediately follows the currently running function. It is important to note that as the progress arrow moves around, it is not preventing lines of code from running. Each line of code is run in sequence; the navigation buttons control only which line of code to pause at next.

The local variables indicate the state of the function that is currently in scope, and updates with each change of the variable. The movie clip _height property increases as each row of squares begins to be added.

Closing the debug panel terminates the debug session, but allows the movie to keep playing from where it was last paused.

Try It Out

Debugging the Experiment

This exercise uses the debugger to track down the problem with the image loader code.

1.Open the completed tryItOut_debug.fla file, or open tryItOut_debug.fla from the book’s source files at <source file directory>/Chapter 12/tryItOut_debug/.

2.Click to the left of line number for the first line within the init() function. A red breakpoint marker should appear.

3.Choose Control Debug Movie.

4.Click the Step Into button once, and note the state of the movie clip explorer.

5.Continue to click the Step Into button until the end of execution is reached, noting the state of the movie explorer as you go.

How It Works

By using the debugger, you should have noticed that the imageHolder movie clip was, in fact, created. While the experiment disproved the theory, it proved something else. What appears to have happened is that creating the text field deleted the movie clip from the stage. At this point, you would take a closer look at the data being passed into the createTextField() method and notice that both the movie clip and the text field share the same depth. Changing the depth argument for the createTextField() method to 2 fixes the problem. Even better would be to pass in this.getNextHighestDepth() to both methods instead of the actual number because it manages depths for you.

310

Debugging Debugged

Using the Trace Statement

One debugging technique that is low-tech but useful is the trace() statement. You have seen it used many times throughout this book. Although it isn’t very sophisticated, it is about the most useful and reliable debugging tool there is.

Two things that trace() statements are good for are to get a sense of the flow of your code and the state of your project. For instance, trace()can tell you whether and when a function is being executed and what data is being passed to the function. The following example shows a trace() statement at the beginning of a function. When the output from the trace() statement shows up in the output panel, you know that the function has been called, and by the data that is added to the trace() output, you know what data was passed to the function:

function animateText(inputString:String):Void

{

trace(“animateText() - inputString: “ + inputString); // Function code ...

}

If you are unsure about how an if statement is executing, placing trace() statements in each if statement block will tell you exactly how the logic affects the execution of the program. In the following code, trace() statements are used to show the values of the variables being tested in the if statements and also to show which of the if statement blocks are executed:

trace(“variable1: “ + variable1); trace(“variable2: “ + variable2); trace(“variable3: “ + variable3);

if (variable1 == “foo” || variable2 == “bar”)

{

trace(“Breakpoint 1”); // Statements ...

}

else if (variable 3 == “baz”)

{

trace(“Breakpoint 2”); // Statements ...

}

else

{

trace(“Breakpoint 3”); // Statements ...

}

Now debug the image loader code time using trace() statements.

Try It Out

Debugging with the Trace() Statement

This exercise uses trace() statements to track down the problem with the image loading code.

1.Open the completed tryItOut_debug.fla file, or open tryItOut_debug.fla from the book’s source files at <source file directory>/Chapter 12/tryItOut_debug/.

311

Chapter 12

2.Click the first frame in the timeline, open the Actions panel (Window Development Panels Actions), and add the following trace() statements (shown in bold):

init();

function init():Void

{

this.createEmptyMovieClip(“imageHolder”, 1); trace(“imageHolder test 1: “ + imageHolder); imageHolder.loadMovie(“thumbnail.jpg”); trace(“imageHolder test 2: “ + imageHolder); handleLoad();

}

function handleLoad():Void

{

imageHolder._x = 10; imageHolder._y = 10;

trace(“imageHolder test 3: “ + imageHolder); this.createTextField(“description1Field”, 1, 70, 25, 100, 20); trace(“imageHolder test 4: “ + imageHolder); description1Field.text = “Description 1”;

}

3.Choose Control Test Movie.

How It Works

Of course, from trying this with the debugger, you already know where the problem lies, but just pretend for a moment that you do not have that knowledge. The theory being tested by this experiment is that the imageHolder movie clip is not being created. The first trace() statement tests that out by showing whether the imageHolder reference returns a value or returns undefined. It returns a value, disproving the theory. The next theory might be that loading the image could be causing the containing movie clip to disappear, perhaps through a load error. The second trace() statement shows that the movie clip is still there right after the loadMovie() method call, disproving that theory. The next theory might be that the text field is causing the problem. Bracketing the field with trace() statements tests this, and shows that, yes, that is the case.

Commenting Out Code

Commenting out code is another technique for testing a theory. The goal is to comment out the code to a point where the functionality works, and then uncomment code progressively until it stops working. This process can be refined to a point where an individual line can be isolated as the source of the problem.

This technique does not work for every type of problem, nor is it necessarily recommended as a standard debugging technique. Resist using this technique blindly with a constant change-compile process instead of using it to test an actual theory. It is truly helpful for very complex or difficult-to-understand code where it’s simply too complicated to work more precisely.

Remember, you can comment out single lines of code by prefacing each line with // (double slash), and you comment out a code block with /* before the first line to be commented out and */ after the last line to be commented out.

312

Debugging Debugged

Try It Out

Debugging by Commenting Out

In this exercise you comment out code to track down the problem with the image loading code.

1.Open the completed tryItOut_debug.fla file, or open tryItOut_debug.fla from the book’s source files at <source file directory>/Chapter 12/tryItOut_debug/.

2.Click the first frame in the timeline, open the Actions panel (Window Development Panels Actions), and comment out the handleLoad() function, as shown in the bold code here:

function init():Void

{

this.createEmptyMovieClip(“imageHolder”, 1);

imageHolder.loadMovie(“thumbnail.jpg”);

// handleLoad();

}

3.Choose Control Test Movie.

4.Uncomment the handleLoad() call, and comment out the line with the createTextField() method.

5.Choose Control Test Movie.

How It Works

The goal of using the comment-out method is to start with something that works, and then comment out code until it stops working. By commenting out the handleLoad() method, you test whether the code works without that function. Because it does, the theory that imageHolder is not being created is disproved. You then uncomment the function and you then comment out the most likely source of the problem within the handleLoad() method. By commenting out only that suspect line, you establish a baseline for when you try running it with that line re-enabled. If it stops working again after commenting out that one line, you know that the theory is wrong and that you should look elsewhere. Because the code worked, you know that the commented-out line is the source of the problem.

Analyze the Results

Once the experiment has been run, it’s time to analyze the results. In the “Debugging the Experiment” Try It Out earlier in the chapter, you used the debugger to test a theory about why the image did not load, and proved that the theory was wrong. You then revised your theory and tested that.

Analyzing the results is generally an ongoing process as you test your theories and as each piece of debug information is revealed to you. Sometimes you come across an a-ha! moment when you suddenly realize what the problem is. When that happens, you think through how to best fix it, make the correction, and perform the test again to ensure that your revision actually works. Other times, you may need to perform the test multiple times, each time adding more trace() information or commenting out more code to get enough information to analyze whether your theory is correct. And occasionally you may not get enough information even after numerous attempts. This may mean that it is time to put your testing aside for a few minutes and take a break. Performing some research online to see whether other people have encountered the same problem may help, and getting the opinion of an experienced Flash developer may also help.

313

Chapter 12

If the results of your testing indicate that your theory is wrong, it’s time to revise the theory and start testing anew. You might make a list of all the possible errors you can think of. For example, if the problem that you are debugging involves an image not loading, some possibilities include the following:

The image is missing from the server.

There is an error in the URL given to load the image.

The code to load the image is not being called.

The movie clip to hold the image is off-screen, or has its _visible attribute set to false.

The movie clip to hold the image does not exist.

Experience will help you to quickly come up with theories that are closer to the mark. If you consistently follow the methodology of developing a theory, testing your theory, and analyzing the results, you should be able to debug even the toughest code.

Summar y

This chapter laid the groundwork for debugging code. Some points to remember include the following:

Compile-time bugs result in the aborting of the compile process and are generally the easiest to debug.

Make consistent use of strong typing to cause as many bugs as possible to be flagged at compile time.

Logic bugs take more effort to fix. They include if statement errors, uninitialized variables, off- by-one and fence post errors, infinite loops, and numerical precision errors.

Follow development best practices such as making code readable, developing in small chunks, and keeping functions small.

The debugging process should closely follow the scientific process of developing a theory, testing that theory, analyzing the results of the test, and revising the theory if needed.

Debugging techniques that are available to use include the use of the built-in debugger, the use of trace() statements, and use of the comment-out technique.

Exercises

1.Split the following if statement into two nested statements to make it easier to see how the statement works:

if ((shipType == “hospital” || shipConfiguration == “peacetime”) && ; (shipDirection == “east” || shipDirection == “west”))

{

// do stuff

}

314

Debugging Debugged

2.Use one or more trace() statements to find out why the second if block is not being evaluated, and fix the problem. (Hint: you may want to review the Date class documentation in the Flash Help panel.)

var tempDate:Date = new Date(2006, 11, 20);

if (tempDate.getMonth() > 5 && tempDate.getMonth() < 11)

{

// Stuff goes here

}

else if (tempDate.getYear() == 2006 && tempDate.getMonth() == 11)

{

trace(“You should see this text”); // Stuff goes here

}

else

{

// Stuff goes here

}

3.The following code should create three squares on the screen, but it only creates a single bow-tie shape. Use the debugger to step through the code to see where the problems lie.

var movieClipHandle:MovieClip;

var baseMovieClip:MovieClip = _level0; var numMovieClips:Number = 3;

for (var i:Number = 0; i < numMovieClips; i++)

{

baseMovieClip.createEmptyMovieClip(“movieClip” + i, 0); movieClipHandle = baseMovieClip[“movieClip” + i]; movieClipHandle._x = i * 30 + 20;

movieClipHandle._y = 20; movieClipHandle.lineStyle(1, 0x000000, 100); movieClipHandle.moveTo(0, 0); movieClipHandle.lineTo(20, 20); movieClipHandle.lineTo(0, 20); movieClipHandle.lineTo(20, 0); movieClipHandle.lineTo(0, 0);

}

4.The following code should extract the sentences from the input string and place them into an array. Instead, the code gets caught in an infinite loop and the array containing the sentences ends up containing no information. Use debug methods of your choice to uncover the issues.

var stopCharacter:String = “.”;

var paragraphText:String = “The quick brown fox. Jumped over the lazy dog. ; Again. And again.”;

var sentenceText:String = “”; var sentenceArray:Array;

var i:Number = 0;

while (i < paragraphText.length)

{

315

Chapter 12

if (paragraphText.charAt(i) == stopCharacter)

{

sentenceArray.push(sentenceText); sentenceText = “”;

}

else

{

sentenceText += paragraphText.charAt(i); i++;

}

}

// Trace out the array

for (var i = 0; i < sentenceArray.length; i++)

{

trace(i + “: “ + sentenceArray[i]);

}

5.The following code should create two buttons on the screen, one with the label Play, one with the label Stop. They should have a colored background, and the play and stop trace() statements should show up only when the proper button is clicked. Debug this code so that it behaves in the way described.

function invokePlay():Void

{

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

}

function invokeStop():Void

{

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

}

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

{

var buttonHandle:MovieClip; parentMovieClip.createEmptyMovieClip(buttonName, ;

parentMovieClip.getNextHighestDepth()); buttonHandle = parentMovieClip[buttonName]; buttonHandle.onMouseUp = function()

{

callback();

}

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

drawBox(buttonHandle, buttonWidth, buttonHeight, AAAAFF, 333333); buttonHandle.createTextField(“labelField”, 1, 4, 4, 50, 15); buttonHandle.labelField.label = buttonLabel;

}

function drawBox(targetMovieClip:MovieClip, boxWidth:Number, ;

316

Debugging Debugged

boxHeight:Number, boxColor:Number, lineColor:Number):Void

{

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);

}

createButton(this, “playButton”, “Play”, 10, 10, 70, 20, invokePlay); createButton(this, “stopButton”, “Stop”, 90, 10, 35, 20, invokeStop);

317