Example 3 - Creating a Flashlight Effect with Masking

In this example we combine programmatic masking with dragging techniques to create a flashlight effect. We make important observations about visibility and the stacking order of display objects versus their response to mouse events.

Download

Download the well-commented fla file for the swf displayed above.

To create the effect we imported to the Stage two versions of the same photo - a dark one and a normal one -- and converted them to MovieClips. We placed the dark version beneath the normal version and masked the normal version by a programmatically created Sprite. We drew a disk in the masking Sprite which serves as a spotlight. Then we drag the masking Sprite. It is rather staightforward if you simply want the mask to follow the mouse without the user pressing the mouse button. If you want the spotlight to be dragged only after MOUSE_DOWN event, you run into a subtle problem: objects that are invisible or are hidden behind other display objects do not respond to mouse events. A mask is invisible; the visibility of regions in the light photo changes according to the position of the mask and the dark photo is behind it. The code below with detailed comments shows how to handle the problem.

/*
We imported to the Stage two versions of a jpeg photo from our recent PREP workshop at URI. We turned them into MovieClips, lightClip and darkClip. We positioned the clips on the Stage, light version over the dark version, and gave them instance names mcLightPic and mcDarkPic. Now we create a new Sprite, lightSpot. Then we draw a circle in lightSpot. Since lightSpot is a child of mcDarkPic, its position (which is the position of its center) is relative to mcDarkPic or mcLightPic). We position lightSpot in the center of our photos.
*/

var lightSpot:Sprite = new Sprite();

mcDarkPic.addChild(lightSpot);

lightSpot.graphics.lineStyle(1,0x000000);

lightSpot.graphics.beginFill(0x0000FF);

lightSpot.graphics.drawCircle(0,0,50);

lightSpot.graphics.endFill();

lightSpot.x = 175;

lightSpot.y = 132;

/*
We are assigning lightSpot as a mask for mcLightPic. Hence, the only visible portion of mcLightPic is going to be the portion visible through lightSpot. Outside of lightSpot, we will see the background which is the dark image.
*/

mcLightPic.mask=lightSpot;

/*
We want the light spot to respond to the MOUSE_DOWN event. A mask will not respond to a mouse event as invisible objects do not respond to mouse events and the mask is invisible. The invisible portions of mcLightPic will not respond to MOUSE_DOWN either but the visible portions will. Thus, if we assign to mcLightPic an event listener that listens to MOUSE_DOWN, the only part of mcLightPic that will respond is the visible part of mcLightPic; that is, the part under the light spot. This is the effect that we want. The MOUSE_DOWN listener assigns to the Stage a listener that listens to MOUSE_MOVE and allows dragging lightSpot but only within the photos area. The latter part is accomplished via boundedX and boundedY functions defined below. (See our Tour of Drag and Drop Techniques tutorial for an analysis of dragging techniques.)
*/

mcLightPic.addEventListener(MouseEvent.MOUSE_DOWN, startMove);

 

function startMove(evt:MouseEvent):void {

stage.addEventListener(MouseEvent.MOUSE_MOVE, pointMove);

}

 

function pointMove(e:MouseEvent):void {

lightSpot.x = boundedX(mcLightPic.mouseX);

lightSpot.y = boundedY(mcLightPic.mouseY);

e.updateAfterEvent();

}

 

stage.addEventListener(MouseEvent.MOUSE_UP, stopMove);

 

function stopMove(e:MouseEvent):void {

stage.removeEventListener(MouseEvent.MOUSE_MOVE, pointMove);

}

 

function boundedX(inX:Number):Number {

if (inX < 0) {

return 0;

}

if (inX > 350) {

return 350;

}

return inX;

}

 

function boundedY(inY:Number):Number {

if (inY < 0) {

return 0;

}

if (inY > 263) {

return 263;

}

return inY;

}

 

On the next page, we show an interesting effect created by animating a mask with EnterFrame event.

Back to Intermediate Tutorials              Back to Flash and Math Home

We welcome your comments, suggestions, and contributions. Click the Contact Us link below and email one of us.

Adobe®, Flash®, ActionScript®, Flex® are registered trademarks of Adobe Systems Incorporated.