Wednesday, March 30, 2011

Adjusting SWF parameters for ActionScript Project

While creating ActionScript Project in Flex builder (Flash builder) You have no .fla file where it's possible to set background color or dimensions.

Eitherway it's possible to configure those settings. To define them add line like this:

[SWF(width="800", height="600", backgroundColor="#ffffff", frameRate="30")]

before main class definition.

Thursday, March 17, 2011

Sound in flash


Here is short tutorial how to play sound in flash and control it.

Firstly we need to import classes:

import flash.media.Sound;
import flash.media.SoundChannel;
import flash.media.SoundTransform;

also one more for loading file:
import flash.net.URLRequest;

In this example file will be loaded externally. Of course there is possibility to embed it.

Now, we have to create instance and load file into it:

var mySound:Sound = new Sound();
mySound.load(new URLRequest('sound.mp3'));

Now it's time to play and control it. It's possible to initiate playing sound even if it's not loaded. Flash itself creates stream and buffers it automatically. It may happen that sound won't be played when you call play() method because it's not yet buffered enough:


var myChannel:SoundChannel = new SoundChannel();
myChannel = mySound.play();

Now we should stop it. Don't ask me why but you cannot stop sound but whole channel

myChannel.stop();

OK, let's go a bit further. Pause option. There's no ready solution. We have to stop channel. Remember to  save progress before.


pausePosition = myChannel.position;
myChannel.stop();

Position is value from 0 to 1 which holds the progress of played track. Now when we have this information we should modify play so that we can continue from saved moment instead of starting from begin.

myChannel = song.play(pausePosition);

While testing you 'll find that you need one more fix. Stop action should reset position


pausePosition = 0;
myChannel.stop();

Let's add one more thing. Volume control. ActionScript3 allows to configure almost every aspect of playing sound. Such complicated functionality needed many classes. That's why for modifing volume we use another class SoundTransform.


myTransform.volume+=VOLUMESTEP;
myChannel.soundTransform = myTransform;

Initially volume is set to 0.5 so you can switch it both ways.

Remember that every time you start playing sound it's sound's transformations are reseted. So to continue playing after pause with same volume level, you have to assign settings


myChannel = song.play(pausePosition);
myChannel.soundTransform = myTransform;







Friday, March 11, 2011

ADDED vs. ADDED_TO_STAGE

ADDED and ADDED_TO_STAGE are two events that are dispatched on object when this is added as child to displayed parent. But there is a reason why they both exist. Here is small study on differences.

Case #1 - adding object to stage.
in this case we're adding class (named A) to main class which is stage. both listeners are added as in presented code:

public class A extends Sprite
{
    public function A()
    {
        trace('A A()');
        super();

        addEventListener(Event.ADDED, _handleAdded);
        addEventListener(Event.ADDED_TO_STAGE, _handleAddedtoStage);
    }

    private function _handleAdded(event:Event):void
    {
        trace('A added');
    }

    private function _handleAddedtoStage(event:Event):void
    {
        trace('A AddedtoStage');
    }
}


And here is main class code:

public function Blog()
{
    trace('Blog Blog()');
    var a:A = new A();

    trace('adding A to stage');
    addChild(a);
}


Here is result of experiment:

Blog Blog()
A A()
adding A to stage
A added
A AddedtoStage


Conclusion: both events works works similar. What is more, everytime ADDED is before ADDED_TO_STAGE. Flash is not working parallely so there must be some reason of this constant order. If You switch adding listeners result is the same. This shows that ADDED is always dispatched before ADDED_TO_STAGE.

Case #2 - cascade adding objects to stage
Now we add one more object, so structure will look like this:

Stage(Blog) -> A -> B

Main class of Blog stays same as in previous example. Class A is modified to create instance and load into itself object of type B. Here is code of class A:

public class A extends Sprite
{
    public function A()
    {
        trace('A A()');
        super();

        addEventListener(Event.ADDED_TO_STAGE, _handleAddedtoStage);
        addEventListener(Event.ADDED, _handleAdded);

        var b:B = new B();
        addChild(b);
    }

    private function _handleAdded(event:Event):void
    {
        trace('A added');
    }

    private function _handleAddedtoStage(event:Event):void
    {
        trace('A AddedtoStage');
    }
}


And here we have source of class B. It looks like class A in previous case:

public class B extends Sprite
{
    public function B()
    {
        trace('B B()');
        super();

        addEventListener(Event.ADDED_TO_STAGE, _handleAddedtoStage);
        addEventListener(Event.ADDED, _handleAdded);
    }

    private function _handleAdded(event:Event):void
    {
        trace('B added');
    }

    private function _handleAddedtoStage(event:Event):void
    {
        trace('B AddedtoStage');
    }
}


And let's see what now happens:

Blog Blog()
A A()
B B()
B added
A added
adding A to stage
A added
A AddedtoStage
B AddedtoStage


Conclusion: First thing is that an event ADDED is captured in class A twice. Once when object is added to this class as child and once when the object itself is added to parent. Second and most important part delay between capturing those event. This shows that event ADDED is dispatched each time when method addChild (or AddChildAt) are called. And this event is dispatched first. ADDED_TO_STAGE is dispatched when object or it's parent or a structure of objects of many levels are added to displayed class on stage. And this event goes as second. Last thing - ADDED_TO_STAGE event is propagated from stage to it's children and to further levels of descendants


Thursday, March 10, 2011

Simple mask

Mask is a layer that covers our appropriate object. It is always problem what is mask and what is masked. And what should be on mask layer. So here is short description with example. Look at this schema:
From the right:
  • back - complete image that is covered
  • mask - objects and shapes here creates holes through which we see image from back
  • result - this is what we get as result of using mask
Background can be everything. In this example it's a simple image:

_background = new _BackGround();
addChild(_background);

Mask can be simple shape. If it's static it don't have to be added as child to stage. But if we want do some action on mask it's neccesary:

var mask:Sprite = new Sprite();
mask.graphics.beginFill(0xFF6600, 1);
mask.graphics.drawRect(-40, -40, 80, 80);
mask.graphics.endFill();
addChild(mask);
_background.mask = mask;
mask.startDrag(true);

In this example mask is a draggable square that follows mouse cursor. Check it!



Associative array

There no such thing like associative array in ActionScript. It would be too easy. In the other hand every object in AS3 is an associative collection of values. Here is example of how it works:

var assocArray:Object = new Object();

And that is all for creating. to set value we call setter

assocArray.price = 10000;

or more like aray

assocArray['price'] = 10000;

Reading looks similar:

assocArray.price

or

assocArray['price']

More complicated situation is with displaying full array. Trying to trace instance will cause something like this:

[object Object]

Also checking the size or length by variable of method doeas not help because returns zero. The easiest option is to create a for-each loop that displays all variables:

for (var item in assocArray)
{
    trace(item,' : ',assocArray[item]);
}

For counting elements the fastest solution is creating a loop that increments value for each item. But it's not good solution for big structures. In this situation good solution will be own class that controls records with push() and pop() methods.