Depth of Field in flash (DOF)
For my latest game I wanted to simulate DOF in flash. In flash we can apply filters to objects and flash provides a blur filter, this is the base of the work. What we need is a mechanism to coordinate the depths of the objects.
First We build a class that manages everything about DOF. This class needs an array which holds references to all the objects we want to use with DOF. We build a virtual space with the depths of 1 where 0 is the position of the camera and 1 is the point most faraway from the camera. Our class has a function addObject which takes the display object and a depths in our virtual space. Next our class has got a property maxBlur that defines how strong the maximum blur effect will be. And of course there is a property focus which defines the current focus.
In my game I needed the effect animated, so I added a main function which manipulates the focus and recalculates the blur effect for each object.
- package at.lueftenegger.dof {
- import at.lueftenegger.dof.operator.Operator;
- import flash.display.DisplayObject;
- import flash.filters.BlurFilter;
- public class Dof{
- public var maxBlur:Number = 5;
- private var _focus:Number = 0; // 0 -> 1
- private var last_focus:Number;
- public var operator:Operator;
- public function Dof(){
- objects = new Array();
- operator = new Operator();
- }
- protected var objects:Array;
- public function set focus(value:Number):void {
- _focus = value;
- render();
- }
- public function addLayer( object:DisplayObject, position:Number ):void {
- if (position < 0) position = 0;
- if (position > 1) position = 1;
- var l:Layer = new Layer();
- l.dispObj = object;
- l.position = position;
- objects.push(l);
- }
- public function main():void {
- _focus = operator.giveFocusValue();
- if(_focus == last_focus) return;
- render();
- last_focus = _focus;
- }
- private function render():void {
- for ( var i:String in objects) {
- var h:Number = ( (objects[i].position - _focus) < 0 ) ? -(objects[i].position - _focus) : (objects[i].position - _focus);
- var blur:Number = h * maxBlur;
- var filter:BlurFilter = new BlurFilter( blur, blur, 1 );
- var filterss:Array = [];
- filterss.push(filter);
- objects[i].dispObj.filters = filterss;
- }
- }
- }
- }
- package at.lueftenegger.dof{
- import flash.display.DisplayObject;
- public class Layer{
- public var position:Number;
- public var dispObj:DisplayObject;
- }
- }
- package at.lueftenegger.dof.operator{
- public class Operator{
- public function Operator(speed:Number = 0.15){
- }
- public function giveFocusValue():Number {
- return 0.5;
- }
- }
- }
- package at.lueftenegger.dof.operator{
- public class Sinus extends Operator{
- private var speed:Number;
- private var run:Number = 0;
- public function Sinus(speed:Number = 0.15){
- this.speed = speed;
- }
- override public function giveFocusValue():Number {
- run += speed;
- return 0.5 + Math.sin(run) * 0.5;
- }
- }
- }
How to use it
- Create a new FLA file.
- Put some MovieClips on screen and give them names.
- Add the following script.
- var dof:Dof = new Dof();
- dof.operator = new Sinus(0.1);
- dof.maxBlur = 10;
- dof.addLayer( getChildByName("object1"),0);
- dof.addLayer( getChildByName("object2"),0.2);
- dof.addLayer( getChildByName("object3"),0.4);
- dof.addLayer( getChildByName("object4"),0.6);
- dof.addLayer( getChildByName("object5"),0.8);
- dof.focus = 0.4;
exporting image sequences
If there is no reason to keep vector graphics in the swf, I normally replace them with Pngs. The flash player is faster in copying pixels than in drawing curves and lines. So, this brings mostly a better performance. But there are two drawbacks in the flash IDE.
- The export function just animates the main time line. All embedded MCs are standing on their first frame. This results in the fact that you can't export nested animations.
- If parts of the animation are controlled by Actionscript, this parts wont be exported at all.
That was exactly my problem today. And fortunately last week end I started to work with AIR. And in Air2beta you even have the possibility to exit the application after all your work is done. So the logical consequence was to write a pseudo command line tool that creates a proper image sequence of PNGs.(That's why I love to be a programmer, you simply make your solutions.) I call it a pseudo command line tool because you call it from the command line, but air apps are GUI apps, even if you don't need it like in this case.
It's really simple to use: You give it a swf file, an output folder, the size of the images and if you want a name prefix.
This is how a call looks like:
swf2imgseq.exe -if c:\temp\test.swf -of c:\temp\ -width 640 -height 480 -prefix img
I needed that tool quickly to continue with my work, so I didn't take time to implement error checkings.
That means you have:
- to give a proper file path
- the out folder has to end with an slash
- width and height has to be int values
- prefix gets a part of the file name, so your OS gives you some rules about it.
I don't know how the program behaves in case of wrong parameters.
You don't get any warranties and you use it on your own risk.
By the way: I have seen this last week end and I didn't know that. If you install an air app, it will be converted to an .exe file automatically.
download: swf2imgseq.zip


