ActionScript.org Flash, Flex and ActionScript Resources - http://www.actionscript.org/resources
ActionScript, rendering and the playhead
http://www.actionscript.org/resources/articles/956/1/ActionScript-rendering-and-the-playhead/Page1.html
Henrik Andersson
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.
 
By Henrik Andersson
Published on December 5, 2009
 
A small, but in dept explanation of how the playhead and the rendering interacts with actionscript.

Rendering

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.

Rendering

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:

  1. Fire the enter frame event
  2. Move the playhead for each playing movieclip to its new location.
  3. Construct and place the child objects for the new frames.
  4. Fire the frameConstructed event.
  5. Run any framescripts.
  6. 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.
  7. Fire the exit frame event
  8. If the frame rendering is skipped, jump to 1.
  9. Fire the render event and then do a rendering pass.
  10. 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.


The playhead

The playhead

As the previous section mentioned, the playhead is now moved after the enter frame event has been dispatched. This is not the only change in as 3. In movies published for flash player 9, the gotoAndPlay method and family also follows the new event order; The playhead is not moved when the method returns, it is moved during the playhead move step in the rendering loop.

As Adobe eventually realized, this is stupid and causes a lot of issues for people who want to access the instances directly after the method returns, this behavior was mostly scrapped in FP 10. Do note that you must publish for FP 10 to get the fixed behavior; the"old" behavior is kept for FP 9 published movies for compability reasons.

When I said "mostly scrapped", I meant that the behavior is not fully scrapped. If you move the playhead of a child instance, the behavior is fixed, but if you move your own timeline, the old behavior remains.

One thing that may not be clear is when exactly the content of a Movieclip is instantiated for the very first frame. You can define a custom class for MovieClip symbols. If you do, you can choose when the content is created. The content is created when the constructor for the Sprite base class runs. And you can choose when to run the constructor for your base class simply by simply explicitly calling it.

Summary

The new event system has brought in a new set of issues for programmers that work with timelines. Old methods no longer work as expected and old behavior has been replaced and then undone. While it is clear that some of the changes were not properly reviewed, the end result is actually better than previously. We now have more places in the rendering loops where we can run code opposed to previously.