Here are the first 4 pages of Chapter 23 of Essential ActionScript 3.0
Chapter 23. Screen Updates
Conceptually speaking, all screen updates in ActionScript can be separated into two categories: those that occur at regular intervals (scheduled updates), and those that occur immediately following the execution of certain event listener functions (post-event updates). Regardless of the category, all screen updates are automated. In ActionScript there is no general, arbitrary means of requesting an immediate screen update. Instead, new visual content created programmatically or manually in the Flash authoring tool is rendered automatically by a scheduled or post-event update. This chapter investigates ActionScript’s two varieties of screen updates.
While most of this book focuses on pure ActionScript code rather than specific .swf authoring tools, the following discussion requires some basic knowledge of the Flash authoring tool’s timeline and timeline-scripting techniques. If you are unfamiliar with the Flash authoring tool, you should read Chapter 29, before continuing with this chapter.
Scheduled Screen Updates
In ActionScript, screen updates are inexorably linked to the Flash runtime’s animation capabilities. Even pure ActionScript applications created with Flex Builder 2 or the mxmlc command-line compiler are governed by the Flash runtime’s animation-centric screen-update system.
The Flash runtime’s screen-update system is designed to accommodate the Flash authoring tool’s model for creating scripted animated-content. In the Flash authoring tool, animated content is produced manually as a series of frames on a timeline, exactly like the frames in a physical filmstrip. Each visual frame can be associated with a block of code known as a frame script. In very general terms, when the Flash runtime plays an animation that was created in the Flash authoring tool, it adheres to the following screen-update cycle:
1. Execute current frame’s code
2. Update screen
3. Go to next frame
4. Repeat
For example, suppose we have a three-frame-long animation, created in the Flash authoring tool, and each frame has a frame script. The general process by which the Flash runtime plays the animation is as follows:
1. Execute Frame 1’s frame script
2. Display Frame 1’s content
3. Execute Frame 2’s frame script
4. Display Frame 2’s content
5. Execute Frame 3’s frame script
6. Display Frame 3’s content
At steps 1, 3, and 5, each frame script might create new visual content or modify existing visual content. Therefore, a more accurate description of the preceding animation-playback steps would be:
1. Execute Frame 1’s frame script
2. Display Frame 1’s content and render visual output of Frame 1’s frame-script
3. Execute Frame 2’s frame script
4. Display Frame 2’s content and render visual output of Frame 2’s frame-script
5. Execute Frame 3’s frame script
6. Display Frame 3’s content and render visual output of Frame 3’s frame-script
In the preceding list, notice that before rendering the visual output of a given frame script, the Flash runtime always finishes executing that script in its entirety.
** The Flash runtime never interrupts a frame script in order to update the screen. **
The speed with which the preceding six steps are performed is determined by the Flash runtime’s frame rate, which is measured in number of frames per second. For example, suppose the frame rate for the preceding animation is set to a very slow 1 frame per second. Further suppose that each frame script takes exactly 100ms to execute and that each frame’s content takes exactly 50ms to render. Relative to the starting of the animation, the theoretical times at which the preceding six steps would be performed are as follows:
0ms: Begin executing Frame 1's frame script
100ms: Finish executing Frame 1's frame script
1000ms: Begin rendering Frame 1's content and frame-script output
1050ms: Finish rendering Frame 1's content and frame-script output
1051ms: Begin executing Frame 2's frame script
1151ms: Finish executing Frame 2's frame script
2000ms: Begin rendering Frame 2's content and frame-script output
2050ms: Finish rendering Frame 2's content and frame-script output
2051ms: Begin executing Frame 3's frame script
2151ms: Finish executing Frame 3's frame script
3000ms: Begin rendering Frame 3's content and frame-script output
3050ms: Finish rendering Frame 3's content and frame-script output
Notice that after each frame script has finished executing, the Flash runtime does not immediately update the screen. Instead, it renders the script’s output at the next scheduled frame-render time. The Flash runtime’s screen updates can, therefore, be thought of as scheduled screen updates because they occur according to the preset schedule dictated by the frame rate.
Hence, an even more accurate description of the preceding animation-playback steps would be:
1. Execute Frame 1’s frame script.
2. Wait until the next scheduled frame-render time
3. Display Frame 1’s content and render visual output of Frame 1’s frame-script.
4. Execute Frame 2’s frame script.
5. Wait until the next scheduled frame-render time.
6. Display Frame 2’s content and render visual output of Frame 2’s frame-script.
7. Execute Frame 3’s frame script.
8. Wait until the next scheduled frame-render time.
9. Display Frame 3’s content and render visual output of Frame 3’s frame-script.
Now let’s suppose Frame 1’s frame script registers an event-listener function, clickListener(), with the Stage instance for MouseEvent.CLICK events. Every time clickListener() runs, it draws a red line to the current mouse pointer position. Here’s the code for Frame 1’s frame script:
import flash.events.*; import flash.display.*; stage.addEventListener(MouseEvent.CLICK, clickListener); function clickListener (e:MouseEvent):void { graphics.lineStyle(2, 0xFF0000); graphics.lineTo(e.stageX, e.stageY); }
Immediately after Frame 1’s frame script executes, clickListener() becomes eligible for MouseEvent.CLICK event notification.
Now suppose the user clicks the Flash runtime’s display area 500 milliseconds after the animation starts playing (i.e., during the wait period described in Step 2 of the preceding list). The clickListener() method executes immediately, but the visual output of clickListener() is not rendered until the next scheduled frame-render time. At the next frame-render time, the visual output of clickListener() is rendered along with Frame 1’s content and Frame 1’s frame-script output.
Hence, an even more accurate description of the preceding animation-playback steps would be:
1. Execute Frame 1’s frame script.
2. Wait until the next scheduled frame-render time. While waiting, if any events are triggered, execute associated event listeners.
3. Display Frame 1’s content; render visual output of Frame 1’s frame-script; render visual output of any event listeners executed during step 2.
4. Execute Frame 2’s frame script.
5. Wait until the next scheduled frame-render time. While waiting, if any events are triggered, execute associated event listeners.
6. Display Frame 2’s content; render visual output of Frame 2’s frame-script; render visual output of any event listeners executed during step 5.
7. Execute Frame 3’s frame script.
8. Wait until the next scheduled frame-render time. While waiting, if any events are triggered, execute associated event listeners.
9. Display Frame 3’s content; render visual output of Frame 3’s frame-script; render visual output of any event listeners executed during step 8.
The preceding steps reflect the Flash runtime’s default screen-update behavior. However, for certain event types the Flash runtime can be forced to update the screen more immediately. For details, see “Post-Event Screen Updates,” later in this chapter.
Now suppose that Frame 2’s content is identical to Frame 1’s content, and that Frame 2’s frame script does not generate any visual output, and that no event listeners are triggered between Frame 1 and Frame 2. In such a case, the Flash runtime does not re-render the display area. Instead, when the frame-render time for Frame 2 arrives, the Flash runtime merely checks whether the screen needs updating. Frame 2 has no visual changes, so the screen is not re-rendered.
Hence, a still more accurate description of the preceding animation-playback steps would be:
1. Execute Frame 1’s frame script.
2. Wait until the next scheduled frame-render time. While waiting, if any events are triggered, execute all registered event listeners.
3. At frame-render time, check if the screen needs updating. The screen needs updating if any of the following is true:
* Frame 1 contains changes to the contents of the Stage made manually in the Flash authoring tool.
* Code in Frame 1’s frame script created new visual content or modified existing visual content.
* Code in a listener function executed during Step 2 created new visual content or modified existing visual content.
4. If necessary, update the screen to reflect all changes detected in Step 3.
5. Repeat steps 1-4 for frames 2 and 3.
For reference in the remainder of this chapter, and in the following chapter, we’ll refer to the screen-update check that occurs at Step 3 as a scheduled screen-update check. Each time the Flash runtime performs a scheduled screen-update check, it dispatches the Event.ENTER_FRAME event (even when the screen is not actually updated). By responding to the Event.ENTER_FRAME event, objects can perform recurring tasks synchronized with each screen-update opportunity. In Chapter 24, we’ll learn how to use the Event.ENTER_FRAME event to create animated content entirely through code.
Ready for one last hypothetical scenario? Suppose we remove frames 2 and 3 from our animation, leaving Frame 1 only. As before, Frame 1’s frame script defines the MouseEvent.CLICK event listener, clickListener(). Once Frame 1’s content and frame-script output has been rendered (Step 4 in the preceding list), the animation has finished playing. Nevertheless, in order to allow for continued event-processing, the Flash runtime’s screen-update cycle must remain active. Therefore, for a .swf file that contains a single-frame only, the screen-update cycle is as follows (the following steps apply equally to a multi-frame .swf file that is simply paused on Frame 1):
1. Execute Frame 1’s frame script.
2. Wait until the next scheduled frame-render time. While waiting, if any events are triggered, execute all registered event listeners.
3. At frame-render time, check if the screen needs updating. The screen needs updating if any of the following is true:
* Frame 1 contains changes to the contents of the Stage made manually in the Flash authoring tool.
* Code in Frame 1’s frame script created new visual content or modified existing visual content.
* Code in a listener function executed during step 2 created new visual content or modified existing visual content.
4. If necessary, update the screen to reflect all changes detected in step 3.
5. Wait until the next scheduled frame-render time. While waiting, if any events are triggered, execute all registered event listeners.
6. At frame-render time, check if the screen needs updating. The screen needs updating if code in a listener function executed during step 5 created new visual content or modified existing visual content.
7. If necessary, update the screen to reflect all changes detected in step 6.
8. Repeat steps 5-7.
Steps 5 to 8 in the preceding list repeat indefinitely as long as the .swf file is running in the Flash runtime, thus binding all subsequent code execution to the frame-rate-based screen-update cycle.
In Chapter 20, we learned that “when an empty Flash runtime opens a new .swf file, it locates that .swf file’s main class, creates an instance of it, and adds that instance to the display list as the Stage instance’s first child.” For pure ActionScript programs, immediately after the main class instance’s constructor method completes, the screen is updated. All subsequent screen updates occur in accordance with the frame-rate-based screen-update cycle presented in steps 5 to 8 of the preceding list. For example, consider the following extremely simple drawing program, which emphasizes screen updates by setting the frame rate to one frame per second.
package { import flash.display.*; import flash.events.*; public class SimpleScribble extends Sprite { public function SimpleScribble () { stage.frameRate = 1; graphics.moveTo(stage.mouseX, stage.mouseY); stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveListener); } private function mouseMoveListener (e:MouseEvent):void { graphics.lineStyle(2, 0xFF0000); graphics.lineTo(e.stageX, e.stageY); } } }
The SimpleSribble constructor method creates no graphical content, but does register a listener, mouseMoveListener(), for the MouseEvent.MOUSE_MOVE event. Whenever the mouse moves, mouseMoveListener() draws a line to the current mouse position. However, that line is not actually displayed on screen until the next scheduled screen update, which occurs once per second. Hence, once every second, the Flash runtime updates the screen with a series of lines showing the mouse pointer’s path through the display area since the last screen update. For a smoother drawing effect, we could increase the frame rate to 30 frames per second, or we could force immediate screen updates using the techniques described later under “Post-Event Screen Updates.”
Let’s review some of the key points covered so far:
* ActionScript’s screen-update system is fully automated.
* For pure ActionScript applications, the frame rate can be thought of as the number times per second the Flash runtime automatically checks to see if the screen needs updating. For example, if the Flash runtime’s frame rate is 1, then all visual changes made by a program will automatically be rendered once per second; if the frame rate is 10, then visual changes will automatically be rendered 10 times per second (every 100 ms).
* If the frame rate is very low (say, in the range of 1-10 frames per second), then there may be noticeable delays between the execution of code that generates visual output and the rendering of that output to the screen.
* Each time the Flash runtime performs a scheduled screen-update check, it dispatches the Event.ENTER_FRAME event.
* Flash Player will never interrupt the execution of a block of code in order to update the screen.