Archive for the 'Flash' Category


Gradients and masks in actionscript

Quick post to describe how to apply a gradient mask to a display object in AS3 (& AS2).

#1 Put your gradient mask on the stage – lets call it gmask
#2 Put the object to be masked on the stage.
#3 Set both the mask and the ‘object to be masked’ to cacheAsBitmap
#4 Apply the mask to the object

In #AS3
gmask.cacheAsBitmap = true
obj_to_be_masked.cacheAsBitmap = true
obj_to_be_masked.mask =gmask

In #AS2
gmask.cacheAsBitmap = true
obj_to_be_masked.cacheAsBitmap = true

It really is as simple as this.
Note to designers: Gradient masks can’t obviously be done directly from the IDE (see below), but these three lines can be placed on the timeline if so desired.

To put a gradient mask on dynamic text you will need to place the text within a container (movieclip/sprite) and mask that.

The object to be masked can also contain animation, text or video though this will require a bit more processor as the bitmap will need to redraw on each frame. Often this is well worth it as the effect can be great.

There is a way of achieving this same effect with no code at all and here it is:

#1 Put your gradient mask on the stage – lets call it gmask
#2 Put the object to be masked on the stage.
#3 Put both of these items into a movieclip/sprite (the container) making sure the mask is on a layer above the object
#4 Give the mask a blend mode of ‘Alpha’
#5 Give the ‘container’ a blend mode of ‘Layer’

And there you have it. Gradient masking achieved with blendModes and absolutely no code.

Benchmarking the two gradient mask methods:
I used each method to mask an embedded video – then placed an instance on the display list and ran at varying frame rates.
Initially there was negligible difference between the code and blend mask methods. I ramped up the FPS to 120 and put four instances of the video on screen. With this set up the code method (cacheAsBitmap) was up to 4% faster than the blendMode Mask method.

Conclusion: The code method is faster but very marginally. If you are desperate for a bit of extra juice go with code.


Fastest Way to Copy An Array: Concat() or Slice(0)

What is the fastest way to copy an array? Concat or Slice? There is only one way to find out. FIGHT!

OK, so we can dismiss any kind of for-loop – far too slow, so that leaves us with:
1) array.concat() – i.e. concatenate an array onto nothing and deliver that as a new array.
2) array.slice(0) – i.e. return a new array consisting of all of the elements of the old array – from 0 till the end (up to a max of 16777215)

I’ve set up an array with a cool 1million entries (ok, it is not big, and it is not clever so it certainly isn’t cool). I need to copy this. The following code executes each method once on every iteration. It keeps a running total and records the average time each takes. I’ve limited the code to 100 iterations.

import flash.display.Sprite;
import flash.text.TextField;
import flash.utils.*;
public class TestConcat extends Sprite
private var iteration_count:int=0
private var concat_total:int=0
private var slice_total:int=0
private var clone_total:int=0
private var tf:TextField = new TextField()
private var test_array:Array = [];

public function TestConcat():void
tf.x = tf.y = 100; tf.width = 600;

//Set up array to copy
for(var i:int = 0; i < 1000000; i++) test_array.push(i);
//Mouse click to rerun test
stage.addEventListener(MouseEvent.CLICK, go);
//First run

private function go(e:Event = null):void
addEventListener(Event.ENTER_FRAME, iterate)

//Loop through tests
private function iterate(e:Event=null):void
concat_total +=testConcat()
slice_total += testSlice()
clone_total += testByteArrayClone()
tf.text = "Av. Concat time=" + (concat_total / iteration_count)
+ "ms Av. Slice time=" + (slice_total / iteration_count)
+ "ms Av. BA Clone time=" + (clone_total / iteration_count) + "ms";
if(iteration_count<99) removeEventListener(Event.ENTER_FRAME,iterate)

//test array slice
private function testSlice():int
var time_slice_start:Number = getTimer();
var slice_copy:Array = test_array.slice(0);
return getTimer()-time_slice_start

//test array concat
private function testConcat():int
var time_concat_start:Number = getTimer();
var concat_copy:Array = test_array.concat();
return getTimer()-time_concat_start

//test BA Clone method
private function testByteArrayClone():int
var time_concat_start:Number = getTimer();
var concat_copy:Array = clone(test_array);
return getTimer()-time_concat_start

//Clone method for Deep Objects(via Bruno)
private function clone(source:Object):*
var myBA:ByteArray = new ByteArray();
myBA.position = 0;

On my laptop I’m clocking the concat at 14ms and the slice at over 29ms.

So a conclusive result. concat is twice the speed (with large arrays – the difference diminishes considerably with smaller arrays)

Give the code a few run throughs and see what you get. Let me know if your results are markedly different.

I have updated the code and added a swf to try out here and the source code here

Fastest way to copy an array

Test the array copy for yourself

I’ve also added in a test for the Byte Array Clone method suggested by Bruno (see his comments below). This method seems a great one for copying ‘deep’ arrays – arrays of complex objects (arrays, objects or other types). In this context and test (copying shallow arrays) the instantiation, writing and reading adds too much overhead. I’ll need to test this in a useful context: with deep arrays.

Demo: Array Copy test


Keeping Lip-Sync in Sync

I’m currently working on a project where I have been handed a lot of movieclips with animated mouths to be sync-ed with spoken audio triggered from the library. Each sentence had been put together in a separate movieclip. Obviously this method exposes the frame rate on slow computers leading to loss of lip-synchronisation. I was told to go through all of the moveiclips and add the audio to the timeline – a very inelegant solution that would take a lot of time with poor results.

I came up with a simple solution that basically just pushes the playhead forward everytime it drops out of sync. I use the frame rate and getTimer to work out where the playhead should be on each iteration. If the playhead drops then it is moved to the position it should be at.

Very simple – saved me a lot of time.

private const FPS:int = 30//Current frame rate
private const ERROR_MARGIN:int=1
private var start_time:int
private var last_frame:int=0//Keep track of last frame to see if mc has stopped playing
private var loop_started:Boolean=false

public function sayPhrase(phrase:String) : void
last_frame=0 //reset last frame
start_time = getTimer()

private function lipSyncTracking(e:Event = null):void
if (mouth_mc.mouth)
var cframe:int = mouth_mc.mouth.currentFrame //get the current frame
var ctime:int = getTimer() //current time
var time_expired:Number = (ctime – start_time )
var target_frame:int = Math.floor((FPS/1000)*time_expired)
if(target_frame>1 && cframe>1)loop_started=true //need to check for looping
if (cframe == last_frame || (cframe==1 && loop_started))
{//MC must have stopped or looped back to beginning
{//If frame is out by the margin of error then correct
if (target_frame >= cframe + ERROR_MARGIN)

last_frame = cframe


Reasons to be Creative 2012

FITC Amsterdam 2012

Flash on the Beach 2011

Flash on the Beach 2010

Swingpants at Flash on the Beach

Flash on the Beach 2009

Swingpants at FOTB2009

Twitter Updates