Tuesday, 5 June 2012

Custom Events

After a while I return to a subject that you certainly come over, again and again... at least I do.

Almost a year ago I made an article on how to make functions callbacks. You can read the article here.

Although I took too long to make a new article on this issue, I prefer this method to the callbacks. The reasons: efficiency and simplicity.

A big difference from normal events in AS3 like Events or MouseEvents is that you have several types of events in these two classes, but you cannot send anything else than... the event itself.

When you make a custom event, you can make it send any type of event defined by you... and as an extra, you can send data too.

So to start, define a new class. I name it CustomEvent (you can make a new folder to separate the classes in your application, just don't forget about the package), and it will extend the Event class in AS3:

package{
    import flash.events.Event;
 
    public class CustomEvent extends Event{
        public function CustomEvent(type:String, data:*=null, bubbles:Boolean=false, cancelable:Boolean=false):void{
        }
    }
}

This is the base skeleton for the class. This will have the same behaviour as the base class Event. The 'type' of event will be determined  by just a unique string constant. You notice that I have included a 'data' parameter in the main constructor, and that this parameter is type '*' which means that it can hold any type of data.
So, the next is the same class with a bit more information:


package{
    import flash.events.Event;
 
    public class CustomEvent extends Event{
        public function CustomEvent(type:String, data:*=null, bubbles:Boolean=false, cancelable:Boolean=false):void{
             super(type, bubbles, cancelable);
             this.data=data;
        }
    }
}

To make this class fully usable by Flash you need to override the clone method. This makes this listener to be forwarded to another listener. The clone method makes a direct copy of the object and returns it.
So, the class with the clone method:


package{
    import flash.events.Event;
 
    public class CustomEvent extends Event{
        public function CustomEvent(type:String, data:*=null, bubbles:Boolean=false, cancelable:Boolean=false):void{
             super(type, bubbles, cancelable);
             this.data=data;
        }


        public override function clone():Event {
return new CustomEvent(type, data, bubbles, cancelable);
}
    }
}

The only thing missing is defining the events names. This can be any name, and are defined as public static strings, like this:


package{
    import flash.events.Event;
 
    public class CustomEvent extends Event{
        public static const EVENT_FIRED:String="Event_Fired";


        public function CustomEvent(type:String, data:*=null, bubbles:Boolean=false, cancelable:Boolean=false):void{
             super(type, bubbles, cancelable);
             this.data=data;
        }


        public override function clone():Event {
return new CustomEvent(type, data, bubbles, cancelable);
}
    }
}


That's it. Our Custom Event class is done. Now, how do I fire this?

As an example the next class will add a button to the display list. Once the user clicks in it, it will fire the 'EVENT_FIRED' event.


package{
    import flash.display.MovieClip;
    import flash.events.MouseEvents;
    import CustomEvent;
 
    public class AddButton extends MovieClip{
        private var myButton:MovieClip=new MovieClip();


        public function AddButton():void{
             this.addChild(myButton);
             myButton.addEventListener(MouseEvent.CLICK, onClick);
        }


        private function onClick(evt:MouseEvent):void {
dispatchEvent(new CustomEvent(CustomEvent.EVENT_FIRED);
}
    }
}


To caught this event you just listen this event as you normally would with any event.

One that is missing explanation is 'how do I send data with this, and how do I get it?'.

Glad you asked.

From the previous example imagine that when you click the button you want to send the string "custom event dispatched".

Replace the dispatchEvent to include this string, like this:
dispatchEvent(new CustomEvent(CustomEvent.EVENT_FIRED, "custom event dispatched");

When you listen to this listener you have to process the event for any data, like this:
...
public var anotherButton:AddButton=new AddButton();
...
anotherButton.addEventListener(CustomEvent.EVENT_FIRED, onAnotherClick);
...
private function onAnotherClick(evt:CustomEvent):void{
     trace(evt.data); //This will trace the string
}

It mihght feel confusing at the beggining but once you get the hang of this you'll throw the function callbacks... your back :)

Cheers.

Tuesday, 17 January 2012

How to Format Text in Actionscript III

In the last article I've shown you a way to embed fonts in Actionscript. That process implies that you will have to embed the font on your compiled and final SWF file. This means that you final SWF will increase, and in some cases dramatically, because you are making the fonts you want to use available in your compiled code.

At this project that I'm working on, this is something we can't do, due to limitation on the hardware we're using. And beacuse the skinning of the application can change, so the fonts can be changed also.

For this purpose we use font embedding but, the fonts will be stored in external, and dedicated SWF files.

To start this process, a first step is to make a SWF file just for the font:
- Open a new FLA file in Flash;
- Place the following code in the first and empty frame of the timeline:

[Embed(source='ARIAL.TTF', fontName = 'Arial', mimeType="application/x-font", unicodeRange="U+0020-U+007E")]
var arial:Class;


Font.registerFont(arial);

This code is explained in the previous article. So if you came here directly and don't understand what's in here, just go there and see what this means.

This SWF will only have the embed characters you tell on the unicodeRange. So if you use any other characters with this font, they won't appear. So make sure your character range is correct.

Compile the file and place it on your local folder or in a "fonts" folder. In this case I will call it arial.swf.

To use this in your code just to simply something like this:
- In your AS3 class define a new Loader variable to keep to load the font:

private var fontLoader:Loader = new Loader();

- Load the font in the main constructor, or wherever it may suit your needs like this:

fontLoader.load(new URLRequest("sections/swfs/fonts/arial.swf"));

- After this, whenever you want to use the font in a textField you need to use the TextFormat to assign this font and change text appearance, like this:

var myText:TextField=new TextField();

myText.defaultTextFormat = new TextFormat("Arial", 38, 0x2DAAFD, true);
myText.selectable = false;
myText.text = "Hello World!";

NOTE: In the TextFormat, "Arial" is the name you gave the font in the Embed in the font SWF file.


This method makes easier to use and change fonts dynamically, for example defining a font to be used in a textField through an XML file.

Happy coding!


How to Format Text in Actionscript II

Some time ago I posted a way to format text using the fonts available in your system that you should, in the first place, import to your library and then use it on your code.

Meanwhile I had a new project where I was asked to come up with a way to use fonts. This project is to be embeded in a set top box, so there's a limitation about the fonts you can use. That's if the box has any available for you to use.

In this case there's no font I can use, so I have to "install" my fonts on the box in order to Flash to recognize them.
Another limitation is that the software can use a font, and I mean any font, that the Design department comes up with. This means that at some point I can have more or less fonts installed on the system. If we can't install fonts on the box, how can I use fonts as I please?

There's two possible answers for this:

One is using a Flex approach using the Embed tag. In you Actionscipt class, where you define your global variables put something like this:


[Embed(source='ARIAL.TTF', fontName = 'Arial', mimeType="application/x-font", unicodeRange="U+0020-U+007E")]
var arial:Class;

As a brief explanation:
- The source must be a font file already in your local folder;
- The fontName is the name you  will call in your code when you want to use the font;
- The mimeType is just something you have to write in order for the compiler to know that this is a font file;
- The unicodeRange is very important because it gives you the possibility of embedding just the characters you want in unicode. In this case "U+0020-U+007E" means a-Z (a to z in lower and uppercase).


For more details about the characters code to use, visit http://unicode.org/charts/ or http://www.rishida.net/tools/conversion/ that will make the conversion for you.


The var arial:Class must come after the Embed tag so that this font instantiated and can be used in the code you make.

For this you'll have to make a final step, which is: In the constructor of you class, register the font using this line of code
Font.registerFont(arial);

After this whenever you want to use this font just to something like this:

var myTextBox:TextField = new TextField();

myTextBox.defaultTextFormat = new TextFormat("Arial", 38, 0x2DAAFD, true);
myTextBox.selectable = false;
myTextBox.text = "My text in Arial";
addChild(challenge);


The "Arial" in new TextFormat("Arial", 38, 0x2DAAFD, true); is the name you gave to the font in the Embed tag, the rest is size, color and whether is bold or not.

The downside of this method is that if you want to use several fonts, you will have to embed them in the code, which mean that you will have to compile each time you change, add or delete a font from the code.

In my case this has to be more dynamic.

The next article will show how you can embed the font through a separate SWF file with the font in it. Just click here to go there.

Happy coding!

Thursday, 25 August 2011

Access modifiers

Hello everyone,

This post is somehow a way to remember some things that might pass you by, specially if you don't use them very often.

Normally when I define my classes, everything is private unless some method or variable must provide values to another class. Even at this point I consider on putting a callback instead of a public value.

But recently I had the need to explain what a "protected" class was.

Well first of all, in AS3, all classes must be declared public, but their methods or variables can be public, private, internal and protected.

So what's the difference between them?

I'll make a brief description of each one. Then you have useful links if you want further explanations.

Public - These are accessible by everyone. Other classes in the same or another package can access these methods or variables.

Private - Only the class can access them. External class can't see them

Protected - These methods and variables are only accessible for subclasses. If you declare a class by inheriting from another with protected methods or variables, this children class can access these. If it's not a children class these methods or variables are inaccessible.

Internal - All methods and variables declared as "internal" are only shared across the same package.

I think is very straightforward, and only depends of what you're doing and how you plan to do things.

The following links can enlighten you a bit more:
Greenthumb
Adobe
Article on Kirupa.com from Senocular

Hope this helps... it did for me ;)

Friday, 17 June 2011

Simple preloader for the Loader Class

I use the Loader class mainly to... well, load an image. It's also used to load external SWF, but at this time, I didn't had the need to use it like that.

My main job, at this point, as an AS3 developer is to produce infographies for a news agency. Some processes ahve change in the way I must now deliver the work, and one big change is that all the assets like images, videos, sounds and xml files, must be in a remote server.

This carries a problem which is a possible lag in time while the SWF tries and loads the assets remotely. You have to take care of this, because the web readers of these infos must have some sort of feedback, or else, nothing happens, and they may think something is broken.

So this time I'll tell you a simple way of making a preloader bar for the Loader class.

Make a simple class to load the image:

package{
     import flash.display.MovieClip;
     import flash.display.Loader;
     import flash.display.URLRequest;


     public class LoadPhoto extends MovieClip{
          private var photoURL:URLRequest;
          private var photoLoader:Loader;


          public function LoadPhoto(url:String){
              photoURL=new URLRequest(url);
              photoLoader=new Loader();
              photoLoader.load(photoURL);
              addChild(photoLoader);
         }
     }
}

This is the minimum to load an image or SWF with the Loader.

If you want to show a progress bar while the data is accessed, you have to draw it. You can add a text field to show the percentage value, but that it's a natural evolution from this progress bar.

Inside the the LoadPhoto function add the necessary code to make a simple line using a Sprite:

progressBar=new Sprite();
progressBar.graphics.lineStyle(3, 0x0000CC); //define thickness and color
progressBar.graphics.moveTo(0,0); //initial point of the line
progressBar.graphics.lineTo(imageWidth, 0); //the line will be on top
progressBar.scaleX=0; //in the beggining the progressBar will be a dot
addChild(progressBar);

Then we have to catch the size of the data that is been received, and of course it's total amount. We have to associate an event to the Loader to catch these values. For that we have to use the ProgressEvent class. So First of all add to the imports block import.events.ProgressEvent.
Then add this line after the end of the LoadPhoto function:

photoLoader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, progressHandler);

Then define a new function that handles this event:

private function progressHandler(evt:ProgressEvent):void{
     progressBar.scaleX=(evt.bytesLoaded/evt.bytesTotal);
}

This last function will receive the loaded bytes and the total byte size, and turn them into a value between 0 and 1, which is what we need to define the scaleX of the Bar. You can later add an event listener to remove the progressBar and show the asset.

In the end the Class with the Loader and a progress bar, will be something like this:


package{
     import flash.display.MovieClip;
     import flash.display.Sprite;
     import flash.display.Loader;
     import flash.display.URLRequest;
     import flash.events.ProgressEvent;

     public class LoadPhoto extends MovieClip{
          private var photoURL:URLRequest;
          private var photoLoader:Loader;
          private var progressBar:Sprite;

          public function LoadPhoto(url:String){
              progressBar=new Sprite();
              progressBar.graphics.lineStyle(3, 0x0000CC); //define thickness and color
              progressBar.graphics.moveTo(0,0); //initial point of the line
              progressBar.graphics.lineTo(imageWidth, 0); //the line will be on top
              progressBar.scaleX=0; //in the beggining the progressBar will be a dot
              addChild(progressBar);

              photoURL=new URLRequest(url);
              photoLoader=new Loader();
              photoLoader.load(photoURL);
              addChild(photoLoader);
 photoLoader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, progressHandler);
         }
         
         private function progressHandler(evt:ProgressEvent):void{
              progressBar.scaleX=(evt.bytesLoaded/evt.bytesTotal);
         }
     }
}

Monday, 6 June 2011

Proxy to read information

Hi,

In a situation where Flash needs to get information from another server, normally a text based information, like XML, there are security issues that need to be overcomed.

If you try to load a URLRequest using a URLLoader object, it will run normally locally, but if you publish it on the net, it won't work. That's because on network the Flash player request a security file to catch the information, from the server it wants to access.

That file is called crossdomain.xml (Maybe I'll do a article about this later), which has to be on the root of the accessed server.

But what if you don't have privileged access to the server and the administrator doesn't want to put that file for you? Probably yesterday I could ask that, but at the time it would involve a lot of people and too much time spent.

So I had to come up with an alternative solution. That solution is by making this request through a PHP (or ASP) script. In my case I'm more comfortable with PHP, and that's what I'm presenting.

It works this way:
1- Flash will make the request, including the url that it wants to access to the PHP file;
2- The PHP file will ask the url given for the information we want to read;
3- Once it gets to the PHP, it will return the information to the Flash.

The PHP won't ask for any crossdomain.xml, so is like someone making the request directly through the address bar of the browser. I read also that there maybe some servers that prevent this mechanism to work, but usually, no. In this case, there's no chance (not that I know of) to get the data unless you can get a privilege to that.

I know that Adobe has a web page with several proxy script for PHP and ASP, but yesterday I couldn't find it, but another did... and I think it's a much better script that the one of Adobe.

So here it is. This code is in http://xmlrpcflash.mattism.com/proxy_info.php

Just copy and paste to a PHP file. Call it "proxy.php" for example.



 
$post_data = $HTTP_RAW_POST_DATA;

$header[] = "Content-type: text/xml";
$header[] = "Content-length: ".strlen($post_data);

$ch = curl_init( $_GET['url'] ); 
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);

if ( strlen($post_data)>0 ){
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
}

$response = curl_exec($ch);     
$response_headers = curl_getinfo($ch);     

if (curl_errno($ch)) {
    print curl_error($ch);
} else {
    curl_close($ch);
    header( 'Content-type: ' . $response_headers['content-type']);
    print $response;
}


?>


On the Flash side, just make the call has you would normally, like this:


var xmlLoader:URLLoader = new URLLoader();

var xmlData:XML = new XML();

 

xmlLoader.addEventListener(Event.COMPLETELoadXML);



xmlLoader.load(newURLRequest("proxy.php?url=http://www.infoimafter.com/net/files/xmlinfo.xml"));



In the last line please regard "proxy.php?url=" followed by the url of the data you want to fetch.



After all this it worked very well. I thisnk this also insures that the data will be forced to refresh. I don't know if is that some servers I use, but it seems that sometimes cleaning the browser cache it's not enough to refresh data, being requested the normal way.



Cheers.

Thursday, 12 May 2011

Loading and resizing image

This is a simple task to achieve. The AS3 has already a component that does this, but if you want to keep your SWF footprint to a minimum, you must consider this solution.

Nothing to it, but I seem to keep always forgetting, since I don't deal with this problem very often.

But here it is for future reference.

First of all we will be using two classes. One is URLRequest, that will capture the HTTP request for a file with its url. The other is the Loader which is used to load external SWF or image files (PNG, JPG or GIF).

First of all import these two classes:

import flash.display.Loader;
import flash.net.URLRequest;

Then instantiate the Loader class outside any function, because we will need it to resize later on.

private var myLoader:Loader;


Inside the loadImage function instantiate the URLRequest class by giving it the file url you which (the url can be a relative path. In this case there's no need to place the HTTP protocol).


Associate the Loader with this URLRequest, and finally add it to the DisplayList.


private function loadImage(file:String):void{
     var myRequest:URLRequest = new URLRequest(file);
     myLoader = new Loader();
     
     myLoader.load(myRequest);
     addChild(myLoader);
}

loadImage("mypicture.jpg");

If you run this, you will see the image "mypicture.jpg" in the stage.

The next step is to scale the image. Try and write the following lines inside the previous function:

myLoader.width=20;
myLoader.height=40;

What happens? The image doesn't appear. So what's going on?

We are trying to scale an object when the object does not have any contents yet.

We have to listen to the myLoader object to see if it has already load the picture and then we can scale.

Write the previous function like this adding the line in red:


private function loadImage(file:String):void{
     var myRequest:URLRequest = new URLRequest(file);
     var myLoader:Loader = new Loader();
     myLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, resizeImage);
     myLoader.load(myRequest);
     addChild(myLoader);
}

Don't forget to add the Event class on the import statements.

The function for resizing by now you should have guessed it:

private function resizeImage(evt:Event):void {
myLoader.width = 45;
myLoader.height = 40;
}

Simple, right?

Happy resizing.


Thursday, 6 January 2011

Usability: Click and Drag cursor

Although it's a common feature in many flash applications a little feedback for users is always welcome... specially when you have a "click and drag" situation.

Recently I came across this request for an infography for a client. I make the infography, but the application didn't have a feedback for the user that that area was meant to be draggable, only a small phrase stating that.

I agreed that this would make sense and made the change.

To substitute the regular Windows mouse icon with one of your own, you must first import the class that controls the mouse UI options, like this:

import flash.ui.Mouse;

This class let's you use two important features for mouse icon... the hide and show options.

If you put it like this:
Mouse.hide();

The mouse icon will disappear, although the mouse still works, but you don't know where it is.

The reverse option will be the show option, like this:
Mouse.show();

You must import also the MouseEvent class, to set the listeners later:
import flash.events.MouseEvent;

Now that we have our hide and show options, how can you make a custom icon and make it follow the mouse position?

Making it simple you have to add a listener for the mouse position, but this is made indirectly, since we are going to listen for any mouse move, and then see where it is.
Making an EnterFrame event can be costly specially if you're application has many pictures or video, like the one I had to make, so we're listening for any mouse move, which is triggered when... you guessed it... the mouse is moved.

First of all, make a movieclip with the icon you wish to appear, and place it in the library with a export actionscript name. I will call it MyLibraryCursor (remember that when making the movieclip, the "plus" sign indicates where will be the click spot for the mouse).

Make a new object with this Library Class:
public var myCursor:MyLibraryCursor;

Then on the init() function of your main class, define your new object, along with two important options:
myCursor = new MyLibraryCursor();
myCursor.mouseEnabled = false;
myCursor.mouseChildren = false;

mouseEnable tells flash if this object receives mouse behaviours. Usually that's a problem when you have many movieclips on the stage, where you can have problems with object focus (this will not disable mouse events).

mouseChildren is put there to prevent event bubbling. Has you know AS3 has a great feature, but sometimes difficult to control and understand, which is the propagation of events between children of a display object (bubbling). This prevents it from happening (a typical case of this is when you have a text box with text, and the mouse is only active when you pass by the line of a letter).

Next we will add the mouse movieclip to the stage:
addChild(Global.myCursor);

Make the "windows" mouse disappear:
Mouse.hide();

And then listen to the MOUSE_MOVE to make it follow the mouse:
this.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);

This calls the mouseMoveHandler function which will move the custom icon to the mouse position:
public function mouseMoveHandler(evt:MouseEvent):void
{
myCursor.x = evt.stageX;
myCursor.y = evt.stageY;
}

And that's it, the basics for replacing the windows cursor, for one of you're own.

Possibly in a future post I will explain other option for this, cleaning a bit the behaviours about this.

You can make a Global class to easy the control of the mouse behaviour if you have to hide, show and turning off and on, between different display objects across your application... this maybe will to go for a later post.

Cheers. 

Sunday, 19 December 2010

MouseButton and HandCursor

Every now and then you may need to use a Sprite or MovieClip with a EventListener. And chances are that 99% of these times it will be a MouseEvent, since these objects are easy to place in custom classes and build an entire interface with Actionscript... at least that will be 100% of the times for me ;)

So in these cases you don't want to make Button objects, but still be able to feedback the user that in "this" object contains an action with the mouse.

Well simply placing three lines of code you can show your user the hand cursor (like it appears in a web page), and have the behaviour of a button. Furthermore the third line prevents the hand cursor not to be active if the button has text in it. Those lines go like this:


var button:MovieClip = new MovieClip();
button.buttonMode  = true;
button.useHandCursor = true;
button.mouseChildren=false;
addChild(button);

Cheers

Tuesday, 12 October 2010

How to count number of lines in a TextField

I was facing this dilema to correct a game were in the textfields the text can have 1, 2 or 3 lines. Depending on the number of lines I wanted to center the text vertically so that when it had only 1 line, it would append a new line "\n" before the text.

This only applies to normal dynamic textfields, not TFL. These have their own methods to center text both horizontally and vertically... much easier.

There's a property called numLines, but this only states that the chosen TextField will have an x number of lines that you specify, you can't use it to return the number of text lines that you see.

So you have to make another type of calculation, and the textfield must be multiline.

var myHeight:Number = myText.height; //store the height of the textfield
myText.multiline = true; //don't need to do this, if it is in the properties panel
myText.wordWrap = true; //same as above

myText.height = myHeight; // here is the trick, try removing this line
trace("DYNAMIC TEXTFIELD HAVE "+myText.maxScrollV+" LINES");

Cheers

Time lapse for FLVPlayback

This is one of those cases when the Adobe documentation is rare, or doesn't help much.

I had a hard time figuring out how to place a bar that would grow along with the playback of a movie in the FLVPlayback component.

First make a custom MovieClip with a rectangle (it can be another shape, but usually rectangles are best for these) and give it a name: myPlayhead

You must have already the FLVPlayback component on stage, with a given name. I will name it: myFLVplayback

For the script we will need to import a class to do this: VideoEvent. This class has several events you can use to get info from the FLVplayback when playing video (http://www.adobe.com/livedocs/flash/9.0/ActionScriptLangRefV3/fl/video/VideoEvent.html)

import flash.video.VideoEvent;


//The movie doesn't start
myFLVPlayback.stop();


//Rewinds automatically if the video is stopped or it reaches the end.
//By default it's false
myFLVPlayback.autoRewind=true;


//Adds the listener for each time the playhead updates it's position

myFLVPlayback.addEventListener(VideoEvent.PLAYHEAD_UPDATE, videoHandler);


function videoHandler(evt:VideoEvent):void{
var totalSeconds:Number = myFLVPlayback.totalTime;
var elapsedSeconds:Number = myFLVPlayback.playheadTime;

var percent:Number=Math.round((elapsedSeconds/totalSeconds)*100);
        
        //The custom seekBar will change it's size according the the percentage
        //of the played movie
seekBt.progressMc.scaleX=percent;
}


Cheers

Custom controls for the FLVPlayback video component

This time I had to help a friend that needed to play some videos in a fancy interface.

The problem was that he didn't want the buttons that Flash provides for video playback, and wanted some flexibility towards mouse events, i.e., beeing able to hide or show the buttons with custom events or mouse events.

For now I will tell how I changed the controls.

First of all you need to make some custom MovieClips for the buttons. One MovieClip per button.

(this is valid for actionscripting the interface, or placing the components directly on stage)

Place the FLVplayback component in the stage and give it a name: myFlvplayback

Place the buttons where you want on the interface, and give them a name: playBt, pauseBt, stopBt,... and so on.

Now the script. You have to associate the buttons to the video component, stating what each button will do, like this:


myFlvplayback.playButton=playBt;
myFlvplayback.stopButton=stopBt;
myFlvplayback.seekBar=seekBt;
myFlvplayback.pauseButton=pauseBt;

That's it. If you run the movie, you'll see that this is enough to custom controls for this video component.

A further step is to make a custom interface with the all buttons inside a single MovieClip. Then you can make your custom autohide function with some MouseEvents.

Cheers

Thursday, 2 September 2010

Logical XOR

Flash doesn't have a logical XOR, only a bitwise XOR. That means that you can only do bitwise operations, or swap number and attribute the result to a variable.

Well I needed a Boolean XOR, like the one with Truth Tables that we know from logical programming. Well this little function takes care of this:

public function xor(lhs:Boolean, rhs:Boolean):Boolean {


return !( lhs && rhs ) && ( lhs || rhs );

}



Cheers,
Leonel

Wednesday, 1 September 2010

Fullscreen... and back

To get your stage into full screen you must do in two steps. The first is to set your stage display state in ActionScript. The other is to allow this scaling in the HTML page.

First of all, place a MovieClip in the stage, by code, or directly in the stage. Give it a instance name.
I will cal mine: fullScr

Associate with fullScr an event listener to catch a mouse event to execute the full screen:

fullScr.addEventListener(MouseEvent.CLICK, handleMouseClick);

Write the handleMouseClick function that will set the display state of the stage. This function will detect the current display state, and change it accordingly. If the display state is NORMAL, it will set it to FULLSCREEN. Otherwise it will be NORMAL again:


private function handleMouseClick(me:MouseEvent):void
{
   if (stage.displayState == StageDisplayState.NORMAL) {
     try{
        stage.displayState=StageDisplayState.FULL_SCREEN;
     }
     catch (e:SecurityError){
        //if you don't complete STEP TWO below, you will get this SecurityError
       trace("an error has occured. please modify the html file to allow    
       fullscreen mode");
     }
   }else {
  try{
       stage.displayState=StageDisplayState.NORMAL;
     }
     catch (e:SecurityError){
       //if you don't complete STEP TWO below, you will get this SecurityError
       trace("an error has occured. please modify the html file to allow 
       fullscreen mode");
     }
  }
}

If you have a video component like FLVPlayback, when you hit fullscreen, this component will take over the screen because it is on top of everything else. To prevent this add this line:

myPlayer.fullScreenTakeOver=false;

Cheers,
Leonel

Friday, 13 August 2010

Function Call Back

This is very handy feature when programming in AS3.


Imagine that you make a AlertBox class, that when called, it makes a custom Alert message. Imagine then, that you can put 1, 2 or 3 buttons, according to the message type. 


If you want to reuse this class in several projects, it's a good idea to tell the different buttons what or where to return when it's pressed.


That's were the Function Call Back enters. After a couple of hours and some search in the web, I came up with a solution, which I want to share.


It's very simple.
First declare in your class a variable that will keep the function reference later on, like this:

private var callBack:Function;

Then when you instantiate the Class, one of the arguments, of the constructor or function, will keep the function name, like this:

createAlert(..., callback){
...
}

Finally inside the constructor or function, you have to attribute the argument to the variable you defined earlier, like this:

callBack=callback;

Then place this variable as a call of some event, like this:

button1.addEventListener(MouseEvent.CLICK, callBack);

... and that's it.


If you want to call the call back function with arguments, instead of a event, just call this way:


typeOfMessage=1;


callback(typeOfMessage);

Sunday, 30 May 2010

Cloning arrays

On the other day I had the need to copy an Array. It was not the first time, but this time I had to make a temporary copy of another array, and put some new data in it and make some calculations.

In this process my need to change the original Array, was none.

The problem is that if you make something like this:

var myArray:Array=new Array("Blue", "Yellow");
var myCopyArray:Array=new Array();


myCopyArray=myArray;

... it works to some extent. You can also do this with concat or slice commands.
This method makes a shallow copy, which means that the copy only stores the reference to the original values, that is, it only stores the memory reference where the values are stored. This means that if you change one of the arrays, the other will change also... This was not what I meant.

I needed to make a hard copy of the array, change it, without changing the original. During the research, I found this generic solution presented in a webpage by Adobe at the following link:
https://www.adobe.com/livedocs/flash/9.0/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00000092.html

As always I transcript the code to here and make a brief explanation.

So the function looks like this:

import flash.utils.ByteArray;

function clone(source:Object):*
{
    var myBA:ByteArray = new ByteArray();
    myBA.writeObject(source);
    myBA.position = 0;
    return(myBA.readObject());
}
Basically what this does is it goes to the memory and gets what is stored in the place where the original Array is referenced. To get the original data and not the reference, it uses the ByteArray class and stores the data in the myBA:ByteArray object. The ByteArray class insures that it copies whatever is stored in the original Array, i.e, Numbers, String, DisplayObjects, whatever...

Pretty handy...

Friday, 21 May 2010

How to erase a element in a Array

I came across this problem recently.


The Array has some methods, and the most common are PUSH, that lets you put an element in a Array. This element will go to the end.


And then you have the POP method, but this only gets the last element in a Array.


Now the question is "How do I delete an element giving the position for that element"?


It's a bit trickier, and it's done using another method called SPLICE.


The syntax is:
splice(startIndex:int, deleteCount:uint... values)


This means:
- startIndex -> Initial position were you want to delete. It's the index position of the Array;
- deleteCount ->This is how many elements you want to delete, that includes the index position you specified in startIndex. If you say 1, then it will delete the index position that you've specified. If you say 2, then it's the index position, and the next element... and so on.


As an example:


var myList:Array=new Array("Blue", "Red", "Green", "Black,"White");


myList.splice(2,2);
trace(myList); //Blue, Red, White


//Green is Index number 2, and then deletes two elements including Green, which are Green and Black

Tuesday, 4 May 2010

Instantiate an SWF as a Class

At the company where I work we add the need to make several SWF that needed to come up, in different timings and according to user navigation. But since we wanted to keep the final application as light as possible, we had the need not to instantiate all the external swf at once.


After some research we found and implemented the following solution: instantiate external swf's as separate classes:


package{
  import flash.display.MovieClip;
  import flash.events.Event;
  import flash.net.URLRequest;
  import flash.display.Loader;
  
  public class Load extends MovieClip
  {
     var storeLoadedObject:Class; //Self explained ;)
     var loader:Loader;
    
     public function Load():void{
         loader=new Loader();
         loader.load(new URLRequest("example.swf"));
         loader.contentLoaderInfo.addEventListener(Event.COMPLETE, completeObjForEdit);
     }


     public function completeObjForEdit(evt:Event):void{
         var className:String="com.gameRoot"; //Document class of loaded file
          storeLoadedObject=loader.contentLoaderInfo.applicationDomain.getDefinition(className) as Class;
        makeLotsOfCopies();
     }


     public function makeLotsOfCopies():void{
        for(var i:uint=0; i<20;i++){
           var copy:MovieClip=new storeLoadedObject();
           addChild(copy);
           copy.x=i*5;
           copy.y=i*5;
        }
     }
  }
}


And that's it.