I write actionscript as a hobby and have gotten very good at understanding the finer points of the language and the platform. I generally hang out on IRC and the forums if you want to discuss something.
ActionScript, rendering and the playhead
This article aims to clear up the confusion regarding how the Flash player deals with playing timelines and how the rendering loop works.
First things first, the player is never drawing when it is executing a script. This means that any script that changes the visible content more than once for each rendering pass will only display the last change made, none of the intermediary steps will be rendered if you don't stop script execution and let the player rend the display list.
The flash player has two ways of rendering, scheduled rendering and on demand rendering. Scheduled rendering is the default method that is used unless you demand a rendering pass manually. The player tries to do a scheduled rendering pass according to the set framerate of the main swf loaded. That is, if you set 30 fps, the player will try to rend 30 times each second.
There is only one framerate for the player; any subsequently loaded movies will be forced to play at the same rate as the main movie. And only the movies in the same sandbox as the main movie are allowed to set the framerate at runtime.
If you have been paying attention, you have noticed that I keep saying "try"ť. This is intentional; the player will skip rendering some frames if it cannot rend them fast enough. After all, the rendering does take time. And the player only has so much time for each rendering pass if it is going to reach the requested framerate.
On demand rendering
The player can do a rendering pass on demand in a few specific situations. To do this, you need to be handling one of the events that allow this. They are the mouse events, the keyboard events and the timer event. To request one rendering pass in such an event, you call the updateAfterEvent method on the corresponding event object. Only one call is needed during each event, the player will remember your request and do the rendering pass as soon as your scripts have finished.
The render event
The render event is one of the less obvious events introduced in FP 9. You need to request that it is dispatched by calling the invalidate method on the Stage class, each and every time you want it dispatched, making it less desirable than the other events that only need the listener registered. But in the end, it can be useful for some purposes. For example, the flash components use it for their delay rendering.
But what does it do? It is actually very simple; it is fired just before a rendering pass is done. This has two subtitle implications; first, if there is no rendering pass, it is not fired. This means that it is not fired if the rendering pass is skipped for a frame during playback. Secondly, it is fired for on demand rendering as well. And it is only fired for DisplayObjects that are rendered.
The rendering loop
One of the least documented parts of the rendering is the rendering loop itself. The player does a lot of different things in a very specific order:
- Fire the enter frame event
- Move the playhead for each playing movieclip to its new location.
- Construct and place the child objects for the new frames.
- Fire the frameConstructed event.
- Run any framescripts.
- Wait for the next step, keeping the framerate no higher than the set goal framerate. During the wait, the player may run scripts due to interactive events being fired. The wait is skipped if the frame is skipped.
- Fire the exit frame event
- If the frame rendering is skipped, jump to 1.
- Fire the render event and then do a rendering pass.
- Go back to step 1.
This new order has caused a lot of issues for people who were used to the old event order, most noticeably, that the enter frame event is fired before the playhead is moved. This means that it is no longer valid to refer to objects constructed during this frame in the enter frame listener. Instead, the available locations are the frameConstructed event and using framescripts.