
O'Reilly Book Excerpts: Flash Hacks
Hacking Flash
Editor's note: Whether you're an expert or a novice, Flash Hacks's collection of tips and tricks for optimizing, creating interesting effects, programming in ActionScript, and more will have you looking like a pro. Today we offer two hacks from the book that show you how to use a Macromedia Director feature to simulate pixel-based fades and wipes, and how to use complex shapes as masks in Flash MX. Next week we'll offer two more hacks: the first on how to make it difficult for others to steal or reverse-engineer your online Flash content; the second on creating a performance budget to understand and adjust where you are expending resources.
  Fake Per-Pixel Transitions
Simulate pixel-based fades and wipes, as
supported in Macromedia Director
Flash doesn't have built-in support for pixel-based transitions. This hack can be
used with other video-friendly hacks to make your static bitmaps
more interesting .
Flash uses a vector-based rendering engine, which
doesn't allow direct access to the individual screen
pixels. This hack depends on the fact that pixels are small, and when
you make something small, it looks like anything else that is small.
The per-pixel transition effect is shown in Figure 1-1.

Figure 1-1. Simulated per-pixel transition, steps 1 through 4
The transition hides (masks) pixels in the first image over time so
that the image disappears a few pixels at a time. Masking off the
first image reveals a second image that is positioned below it, thus
creating the transition effect from the first image to the second
image. The masks used to create the preceding effect are shown in
. Note that for black pixels, the mask
effect shows the first (topmost) image; for white pixels (no mask),
it shows the second (bottom) image.

Figure 1-2. Masks for simulated per-pixel transition, steps 1 through 4
As we shall see, we can make much more complex transitions with little
change.
This hack requires the following steps:
-
Make the fake pixel. In this hack we will create a little 4x4
rectangle.
-
Find a way to make lots of fake pixels. This is done very easily in
Flash using MovieClip.attachMovie( ).
The problem here is that we will have thousands
of fake pixels, and we can't use anything
as processor-extravagant as thousands of onEnterFrame(
) scripts running every frame for the duration of the
effect. Instead, we will use setInterval(
), which reduces our processing overhead
significantly by running code only once per fake pixel for the
duration of the effect.
Make the Pixels
Making
a pixel mask is as simple as
creating a rectangle:
-
Create a new Flash document (File→New→Flash
Document).
-
Use Modify→Document to set the Stage area bigger than 200
200 pixels and specify a white background (any light color will allow
you to see the black rectangle in Step 3).
-
Draw a black rectangle with no stroke (the stroke
wouldn't be seen but would still slow down our
effect).
- Using the Properties panel (Window → Properties), set the rectangle's height and width to 4. Set the X and Y coordinates to 0. You can see the result just next to the registration point in Figure 1-3.

Figure 1-3. A 4x4 pixel mask with its registration point
NOTE: ActionScript gurus might want to draw the mask using the Drawing API, but it would take too long for Flash to dynamically draw all the rectangles we would need for this effect.
- Convert the rectangle into a movie clip symbol by selecting it (with the Selection tool)
and pressing F8 (Modify → Convert to Symbol), which brings up the Symbol Properties dialog box. Name the movie clip symbol dot and make sure you have the export options set up as shown in Figure 1-4 (click the Advanced button if you don't see the Linkage options).
Figure 1-4. The Symbol Properties dialog box
You can delete the movie clip instance from the Stage, since we will
use the MovieClip.attachMovie(
) method to dynamically attach the Library
symbol to the main timeline at runtime. If you want to avoid creating
and then deleting the movie clip from the Stage, you can use
Insert→New Symbol (Ctrl-F8 or &command;-F8) to create
the movie clip symbol directly in the Library.
The effect uses a large mask consisting of these 4x4 squares. The
mask is applied to the first image, and the effect works by masking
additional rectangles over time, causing the second image (which is
below the first) to show through the gaps.
Make Lots of Pixels
On the main timeline, add a new layer and name it
actions .
In the actions layer of the main timeline,
select frame 1 and attach the following script using the Actions
panel (F9):
function drawGrid (theWidth:Number, theHeight:Number):Void {
var initDot:Object = new Object( );
var k:Number = 0;
for (var i:Number = 0; i < theWidth; i += 4) {
for (var j:Number = 0; j < theHeight; j += 4) {
var dotName:String = "dot" + i + "_" + j;
initDot._x = i;
initDot._y = j;
this.attachMovie("dot", dotName, k, initDot);
k++;
}
}
}
drawGrid(200, 200);
The preceding code creates a 200x200-pixel square consisting of our 4
4 movie clips (you can invoke the drawGrid( )
function with different dimensions to create a grid of a different
size). Each pixel is placed at position (i,
j) and depth k on the Stage and
has instance name
doti_j.
The first instance name (situated at the top left of the square) is
dot0_0 and the last one is
dot199_199 (bottom right). You can see the movie
clips created if you run the code in Debug Movie mode
(Control→Debug Movie), but be aware that the debugger will
take some time to display all your movie clips (although it may look
as if Flash has hung up, give it a few seconds!).
TIP:
This effect creates a large number of movie clips;
(200/4)2 = 2500. Flash seems to become
very sluggish if more than 3000 to 4000 movie clips appear on the
screen at the same time (even if you are not moving the clips), so
you are advised not to go far beyond 2500. If you need to mask a
larger area than the one we are working with (200 pixels square),
consider making the constituent rectangles bigger rather than adding
more of them.
Control the Pixels
The trick now is to make the dots disappear on demand. The way to do
this is via
setInterval(object,
"method",
timer), which invokes
the function object.method(
) every timer
milliseconds. Add the following code after initDot._y =
j; in the preceding script:
initDot.timer = 1000 + Math.ceil(Math.random( )*800);
The preceding line creates a property,
timer, which stores an integer between 1000
and 1800 for each dot clip. The 1000 specifies the pause before the
effect starts, and the 800 is the duration of the effect. Both values
are in milliseconds, the standard measure of time in ActionScript.
This hack is based on a mask effect, but Flash allows only one mask
per movie clip. The easy way around this limitation is to create all
our dot movie clips inside another one that acts as the mask. We also
pass in the name of the clip to be masked as a parameter to the
drawGrid( ) function (changes are shown in
bold):
function drawGrid(theWidth:Number, theHeight:Number,
imageClip:MovieClip):Void {
var initDot = new Object( );
var k:Number = 0;
// Create a mask clip to hold all the dots
this.createEmptyMovieClip("mask", 1);
// Assign it as the masking clip
imageClip.setMask(mask);
for (var i:Number = 0; i < theWidth; i += 4) {
for (var j:Number = 0; j < theHeight; j += 4) {
var dotName:String = "dot" + i + "_" + j;
initDot._x = i;
initDot._y = j;
initDot.timer = 1000 + Math.ceil(Math.random( )*800);
// Place the masking dots within the container mask clip
mask.attachMovie("dot", dotName, k, initDot);
k++;
}
}
}
drawGrid(200, 200, image1_mc);
So now we have all our dot clips inside another movie clip named
mask, which we use as the mask for a movie clip
whose name is passed in as a parameter to the drawGrid(
) function. In this case, we use a clip named
image1_mc, which we create later in
. First though,
let's finish off the dot movie clips.
Create the Timers
We already have a timer property for each dot
movie clip. Now let's write the code to make our
dots disappear.
Edit the dot movie clip symbol and add a new
layer named actions (the first layer of a
timeline is traditionally named scripts or
actions and used exclusively to hold your
timeline-based scripts).
In the first frame of the actions layer, add the
following code:
removeMe = function ( ) {
clearInterval(countDown);
this.removeMovieClip( );
};
var countDown = setInterval(this, "removeMe", timer);
The last line of the preceding code uses setInterval(
) to create a timer named
countdown for each dot. It calls the
removeMe( ) function when the timer expires. The
removeMe( ) function clears the interval and
then removes the current dot clip, which creates our
"disappearing pixels" transition
effect.
TIP:
If setInterval( ) is passed a function reference
as the first parameter, such as setInterval(removeMe,
timer);, the value of the keyword this
would be undefined within the removeMe(
) function. Therefore we use the alternative form
setInterval(this,
"removeMe", timer) in
which we pass an object and a method name as the first two
parameters. (In this case, the keyword this is the
object passed as the first argument.) When removeMe(
) is invoked, the keyword this is in
scope, so we can invoke this.removeMovieClip( )
to remove the clip.
Using the Effect
To use the effect, you need to have the two things you want to
transition between on two separate layers, with the first image or
video clip on the top layer, as shown in . You should give the first clip the instance
name image1_mc using the Properties panel. The
second image can be called anything since it is never referred to in
the code.

Figure 1-5. Setting up a transition between two layers
You can see the effect in action by downloading
pixelMask.fla
from this book's web site.
Extend the Effect
By changing the time interval before each dot disappears, you can
create different transition effects. For example, changing the timer
values based on the position of the dots serves as the basis for many
common pixel-based transitions:
// Left-to-right wipe
initDot.timer = 1000 + (Math.random( )*(initDot._x)*10);
// Diagonal wipe
initDot.timer = 1000 + (Math.random( )*(initDot._x + initDot._y)*5);
Final Thoughts
Masking is a very underutilized feature of Flash.
It's one of those features that seems to have no
real use until you delve deeper. No surprise then that many of the
coolest effects seem
to use it extensively!
Pages: 1, 2
|
Next Page |


|