Hack 71 Performance Budget 
A financial budget tells you where you are
spending your money. Create a performance budget to understand and
adjust where you are expending resources.
We saw earlier how to estimate
download times [Hack #66],
allowing you to cram the maximum presentation into the smallest
filesize. Performance has a lower priority in the Flash Player design
than does filesize optimization, which means that although Flash
allows you to create compelling content in very few kilobytes, you
have limited resources from which to extract performance. Although
the total processor cycles available to the Flash Player are limited,
you can control where Flash spends its time. A performance
budget reflects a conscious effort to adjust
the amount of time Flash doles out to each of the parts of your
movie.
Areas of Focus
Like
all budgets, your performance budget should include priorities. That
is, not all aspects of your presentation are equally important. For
example, users notice hiccups in audio tracks more than hiccups in
videos or animation. Designers also tend to lavish attention on
things the typical user won't ever notice or
appreciate. The user generally looks closely only at the things she
is currently interacting with; elements within the
user's "area of
focus" get the greatest attention from her and
therefore should be given priority in your performance budget. Items
in the user's peripheral vision may be ignored
entirely or noticed only when they do something unexpected, such as
shift by a pixel. Therefore, allocating your performance budget and
designing an interface that serves the user's needs
are complementary tasks.
If you can anticipate (or control) the user's area
of focus, and make that perform well, the user gets the impression of
greater overall performance even if peripheral items are static or
perform less well.
For example, in video games (and intensive real-time graphics), items
closest to the viewer in the 3D virtual world are rendered with the
most detail. The detail can drop off significantly with distance;
even if the player notices, it mirrors reality in which things
further away are generally less visible/detailed. Likewise, the
collision detection algorithm [Hack #40] used by distant parts of the
game can be less precise for the same reason—they are not close
enough to be in the user's area of focus. This
allowance frees up some of the performance budget for real-time
lighting, physics, and other trappings of virtual worlds.
Set Process Priorities
There are a number of ways to
give your area of focus the lion's share of the
performance budget. The easiest approach is to simply give the area
of focus an "on-change" event
handler and use a periodic event to update the rest of the movie. For
example, if you are implementing a pong game, you can use an
onMouseMove( ) event handler to control the
user's paddle and an onEnterFrame(
) event handler to control the opponent's
paddle and the ball. If the part of the game that the user controls
is responsive, the entire application feels more responsive.
However, just setting two different priorities
doesn't allow us detailed control over the
performance budget. A better approach is to use several different
priorities. Here we allocate our priorities based on the likelihood
and directness of user interactivity:
- High priority
-
Processes with which the user will interact directly
- Normal priority
-
Processes with which the user will interact indirectly
- Low priority
-
Processes with which the user will rarely or never interact
In terms of a game (the most common high-performance Flash
application), the high-priority process is the
player's ship or character (a.k.a. token).
Normal-priority processes include the enemy graphics; although the
user expects them to move at an adequate speed, the slowdown
won't be as noticeable as long as the high-priority
stuff doesn't slow down as well. The user will just
assume that the slow-moving enemy target is supposed to move slowly.
Low-priority processes are things like the score update or a
scrolling background—the user notices if they break, but if
they work adequately, the user pays little attention.
Low-priority processes can be hard for game designers to identify
because developers are personally vested in every pixel and audio
cue. You'll be more apt to let go of your rigidly
held beliefs if you realize that everything you deprioritize allows
you to lavish more attention (or performance) on things that matter
more. And don't forget that the sound effect that
was cute the first time might get really boring after the user hears
it a thousand times. So the best option is to put your prototype
version in front of beta testers. Ask them what they like, what seems
too slow, what they find annoying, and so on. By definition, these
are the people you are trying to entertain, attract, or serve, so
listen to their feedback.
You can also trick your audience into thinking you are doing more
than you actually are. For example, you can have a scrolling star
field with many stars when the game is displaying the static high
score table, but as soon as the game starts, you can reduce the
animation complexity [Hack #70] .
The user won't notice if you slowly drop the number
of stars as the game gets faster and more difficult. He is more
likely to be concentrating on getting to the next level!
Implementation
Once
you decide on your priorities, you need to implement them in
ActionScript. Since you can't just tell Flash that
something is important, you instill priorities indirectly via the
programming techniques and events you choose.
High-priority events can use either:
Because high-priority events occur more frequently than the frame
rate, the high-priority event handlers must include an
updateAfterEvent( ) command to redraw the Stage
between frames.
Normal-priority events can use an onEnterFrame(
) event handler to perform operations at the same
frequency as the frame rate.
Low-priority events can use either:
Figure 9-8 shows the interface for a scrolling
video game. In this example, we'll set different
priorities for different aspects of the game.

game01.fla from
this book's web site shows the main routine for a
typical FLA configured using a performance budget philosophy; look at
the script on frame 2 of the movie clip mc.world
for the main listing.
Although ActionScript purists might balk at the fact that a script is
attached to a movie clip, game design is as much about animation as
it is scripting, so you will find animation mixed with code, and very
rarely will you find an entire game on a single frame. For example,
if you look at the player's ship (symbol
mc.ship in the Library), you will see that the
explosion sequence is a keyframe animation rather than 100% scripted.
Although you could use scripted timers to control the explosion
animation, the timeline animation is easier to create, requires
little forward planning, and is more likely to be comprehensible to
designers who might have to edit it.
Here is how the three sets of priorities are handled in the FLA
file's code.
The ship sprite is the only high-priority process. The following code
sets up an interval that invokes shipController(
) every 30 milliseconds to redraw the ship:
shipControl = setInterval(shipController, 30);
The background terrain update has a normal priority (to be updated at
the frame rate of 18 fps), so it is scrolled every frame by setting
the onEnterFrame( ) handler to
terrainController( ):
terrain.onEnterFrame = terrainController;
The score update is low priority, so it is refreshed only once per
second:
scoreKeeper = setInterval(scoreController, 1000);
You can also see how the system works by simply playing the game (a
far better option!). You will notice that:
The star field scrolls more slowly than the terrain. The stars are
assigned a low priority and update every quarter of a second. This
fact is hidden somewhat by staggering the update—each star
animates once every quarter second, but not all of the stars update
at the same time. The radar display updates at around the same rate as the stars. The
game is designed to make the slow update seem intentional—the
old cathode ray tube radars worked on a slow scan update. A common
trick is to fill blank areas of the screen with things that the user
expects to move slowly, such as clouds and distant hills. The slow
updates for these items seems natural. The player's ship moves much faster (and more
smoothly) than the aliens. Most users won't perceive
the difference because they are focused on their own ship. If they
notice the difference, they are happy to be able to outmaneuver their
sluggish enemies. The aliens, laser, and terrain all move at the frame rate. The score updates very slowly (every 1 second). This is the
lowest-priority process in the game because the user is busy looking
elsewhere. Updating text fields too frequently is one of the biggest
performance killers in Flash. Even a modest amount of text takes a
lot of vectors to draw, especially if Flash is redrawing it every
frame!
This game example shows it is possible to create a fast Flash game
with a reasonably large Stage size. Increasing the size of the
browser window need not kill performance if you structure your games
properly.
Final Thoughts
Using a performance budget doesn't make the Flash
Player faster, but it gives the perception of faster performance,
just as a preloader status bar makes the user feel as if the download
is faster. You should identify the elements that need to update
frequently and allocate more of the available performance budget to
them. Likewise, identify the low-priority processes and run them more
slowly to make more time available for higher-priority processes. If
you increase the performance in the user's areas of
focus, the game will feel responsive and the user
won't notice the areas of slower
performance.
|