Using the AMFPHPConnection class

In this post I’ll be talking about a class I’ve made called AMFPHPConnection that extends Flash’s NetConnection object. This class eases and enhances the process of using AMFPHP for Flash remoting. But before we begin, just a few notes: I’m not the usual author, and you’ll need to know how to use AMFPHP the normal way, or you may not get some of the terminology. If you want to learn how to use it, I have a series on my YouTube channel for that purpose, go here to watch it: http://www.youtube.com/user/BlackBulletIV#grid/user/CAD2DAE46A04939D

First go and download the class from here: http://www.nova-fusion.com/cms/FileFolder/AMFPHPConnection.zip

This zip file contains the minimized class in it’s package folders: com/novafusion/net/AMFPHPConnection.as. It also contains readable version of the class, which has documentation, comments and more whitespace; it is: AMFPHPConnectionReadable.as. If you actually want to use this class instead, rename it to AMFPHPConnection.as and place it in the proper package folders. The zip file also contains package details similar to what I’m talking about now, and instructions similar to what I’m going to be talking about below. Now let’s get onto how to use it.

Setup

To get started, import the class:

import com.novafusion.net.AMFPHPConnection;

Next create a new instance, you can call the variable name whatever you like but I’ll go with connection:

var connection:AMFPHPConnection = new AMFPHPConnection("http://localhost/amfphp/gateway.php");

When you create a new instance, you are expected to pass in one parameter, the path to your AMFPHP gateway.php file. When you create the instance the class will automatically set up a connection and a responder for your function calls. If you would like to change the gateway location at any point do this:

connection.gateway = "http://www.some-other-server.com/amfphp/gateway.php";

This will set the gateway location in the class and reconnect to that server. Access the path to the current gateway this way:

connection.gateway

Quick Service Referencing

Quick service referencing helps a lot in speeding things up and reducing the amount of code you have to right. If you have a service you use a lot in your code, the connection class can store it for you and cut down how much you have to type to reference it. Examples of referencing strings are:

"FlashPHPTest"; // just a class name, but this could be a folder name
"UsingAMFPHP.TalkBack"; // folder and a class inside it
"UsingAMFPHP.TalkBack.put_together"; // folder, a class inside it, and a method inside the class
"FlashPHP" // part of a class name (could be folder or method name)

You can basically store any string in them, and reference it quickly when calling a service. You could use each of these reference strings in calls like this:

"$1.spitBack"; // just a class name, but this could be a folder name
"$2.put_together"; // folder and a class inside it
"$3"; // folder, a class inside it, and a method inside the class
"$4Test.spitBack" // part of a class name (could be folder or method name)

You use your references with a dollar sign and then it’s number (which is assigned to it in the order you add them to the class). As you can see this will greatly reduce what you have to write in your code.

You can add service references in two ways. The first is to add them in when constructing the class:

var connection:AMFPHPConnection = new AMFPHPConnection("http://localhost/amfphp/gateway.php", "FlashPHPTest", "UsingAMFPHP.TalkBack");

The second way is to add them in with a method provided:

connection.addServices("FlashPHPTest", "UsingAMFPHP.TalkBack");

You can add as many as you like at one time, and use the method as many times as you like. You can also remove service references like this:

connection.removeServices("FlashPHPTest", "UsingAMFPHP.TalkBack");

It’s not recommended that you remove service references, as it might generate confusion as to the order in which to reference them afterwards (just more for you to keep track of).

Calling Services

To call a service, use this method and pass in your service and parameters (not the responder! That’s taken care of for you):

connection.talk("SomeService.someMethod", "Some parameter", "Another parameter");

The function is called talk because of confliction with the NetConnection object’s call method. However you can still use that method, like this:

connection.call("SomeService.someMethod", null, "Some parameter", "Another parameter");

You can pass in the responder either as null (the object’s responder object will be used instead, which is what you want), use connection.responder (replace connection with your instance name), or pass in your own custom responder (note that result and fault listeners won’t work).

You can use quick service referencing in your calls like this:

connection.talk("$1.spitBack", "Hello world!");

Just use strings in the style shown in the quick service referencing section and all will be well.

Result and Fault Listeners/Handlers

We need to see up some listener/handler functions to respond to results and faults from AMFPHP:

function onResult(event:Event):void {
// do whatever
trace(connection.result);
}
function onFault(event:Event):void {
// do whatever
trace(connection.fault);
}

Notice that instead of receiving objects they actually receive plain event objects; that’s because they’re triggered by custom event listeners. You access the last result object with connection.result (replace connection with your instance name) and the last fault with connection.fault (replace connection with your instance name). Now how do we add the listeners for these functions? Here’s how:

connection.setListeners(onResult, onFault);

Just pass in the result function and the fault function and they’ll be triggered for their respective events. Now you don’t have to set either one, if you want to set the fault handler but leave the result handler as it is just leave the onResult function as null. Now be careful about these handlers, when you set them like this they become the default handlers for all calls. One way to get around this is to remove the listeners in the on result or on fault functions, using this:

connection.removeListeners();

You could do that, but there’s a better way to do it. Set the third parameter of setListeners() to true; this will make these listeners only last for one call, and on the next result or fault they will be removed. Here’s how:

connection.setListeners(onResult, onFault, true);

You could also add listeners the harder way like this:

connection.addEventListener(AMFPHPConnection.RESULT, onResult); // For results
connection.addEventListener(AMFPHPConnection.FAULT, onFault); // For faults

And of course to remove them you just use them same code, just change the function to removeEventListener().

Conclusion

Hope that helps! Here’s a sample application to give you some perspective on how this class lessens your code when using AMFPHP:

import com.novafusion.net.AMFPHPConnection;

var connection:AMFPHPConnection = new AMFPHPConnection("http://localhost/amfphp/gateway.php", "UsingAMFPHP.TalkBack", "FlashPHPTest");

function result(event:Event):void {
trace(connection.result);
}

function fault(event:Event):void {
trace(connection.fault);
}

connection.setListeners(result, fault);
connection.talk("$1.put_together", "tom", "bob");
connection.talk("$2.spitBack", "tom");

How to Pad a Number with Zeros + Simple Counter

At some point using Actionscript you may need to display a number that must always occupy a predetermined number of character spaces. An example would be a rolling game timer with a 5 digit display. For example, when the timer hits 33 seconds, the digits would display like so: 0 0 0 3 3

It is very simple to pad your number to whatever length of characters you would like.

package com.frigidfish.utils{

public class PadZero {

public static function convert(inputNumber:Number,numberOfDigits:int):String {

var paddedString:String=inputNumber.toString();
while (paddedString.length < numberOfDigits) {
paddedString = "0" + paddedString;
}
return paddedString;
}
}
}

Save this as3 class to a folder relative to your flash document /com/frigidfish/utils/PadZero.as

Here is an example usage:

import com.frigidfish.utils.PadZero;

trace(PadZero.convert(33,5));
// traces 00033

I use this little converter all the time with customized timers and counters.

If you would like a simple example of a timer, you could do something like this:

// Simple Counter
// Add 4 text boxes to the stage.
// Name their instances from left to right:
// digit0, digit1, digit2, digit3

import com.frigidfish.utils.PadZero
import flash.utils.Timer;
import flash.events.TimerEvent;

var counter:int = 0;
var timer:Timer = new Timer(1000);
timer.addEventListener(TimerEvent.TIMER, addOne);
timer.start();

function addOne(event:TimerEvent):void{

counter ++;

if(counter &gt; 9999) counter = 0;

var t:String = PadZero.convert(counter,4);

digit0.text = t.charAt(0);
digit1.text = t.charAt(1);
digit2.text = t.charAt(2);
digit3.text = t.charAt(3);
}

You could make custom digits with your own artwork to spice up your timer. Have fun experimenting with Flash Actionscript 3!

Freeing up memory for Garbage Collection

Something that I’ve been noticing lately with Flash / Actionscript 3 is the need to pay close attention to how you are cleaning up your objects after you are done with them.

I’ve been working with a great as3 debugging tool called “De MonsterDebugger”. Strange name but great tool. Check it out here: http://www.demonsterdebugger.com/

Basically you just download the debugger and import the class:

import nl.demonsters.debugger.MonsterDebugger;

then as the first line in your constructor function:

new MonsterDebugger(this);

Now you just open the air application that came with the download and it will track everything that happens in your class in the interface. You can run functions from it as well. It rocks!

Anyway, my point being that as I was running it on some of my programs I noticed a significant amount of memory leakage on some of the classes. Here are a few tips to help flash along with garbage collecting your old used up objects.

One thing I like to do is to create a destroy() function at the end of my classfiles. The job of this function is to reset all variables possible in the script. I’ll explain more in a moment.

The ‘delete’ keyword:

This is a somewhat misunderstood keyword in as3 because it only works on dynamically created variables. let me explain. take the following code for example:

var fluffy:Cat = new Cat("happy");
var sally:Cat = new Cat("angry");

// now somewhere along the way we want to remove fluffy
delete fluffy;
// oops! This generates an error. This is because the delete
// keyword only works on dynamic properties.
fluffy = null;
// Ok, so this sets fluffy to null but references to fluffy elsewhere
// in the code may still cause Garbage Collection to not be able to
// clean it from memory.

So I have discovered that the only way to be sure that your flash variables will be garbage collected and the memory will be released is to make the variables in your classes dynamic by using arrays or objects to store them.

You could do this like so:

var cat:Object = new Object();

cat["fluffy"] = new Cat("angry");
cat["sally"] = new Cat("happy");

addChild(cat.sally);
addChild(cat.fluffy);

// ok, now later we can clean up with a destroy function

function destroy():void{

        for(var i:Object in cat){
                removeChild(cat[i]);
                delete cat[i];
        }
}

The destroy function iterates through all objects inside of the cat object and removes them from the display list.
Next, it deletes the property itself freeing it up for garbage collection.

Keep in mind that the Cat class should also have a destroy function that cleans itself out as well!
So the function would be modified to look like this:

function destroy():void{

        for(var i:Object in cat){

                removeChild(cat[i]);
                cat[i].destroy();
                delete cat[i];
        }
}

You can use the De MonsterDebugger to magically watch your memory performance increase dramatically by using this technique. Happy Flash coding!

Hidden Games in as3blog.org

I just realized that there are some hidden games in my banner. This may seem like a strange statement since I made the banner and all the artwork. Well, originally the banner was a concept design for a company that we do projects for called “ThinkFun”. I stripped down the banner but apparently left some ‘hidden’ games.. See if you can find the games hidden in the header banner of this site! I believe there are anywhere from 3 to 6 or so.

By the way, for anyone that has read my Game Grid article, these games all use the concept, so you can see it in action.

Enjoy!

How to use Classes in your Project

Many of the examples that I use in my blog come in the form of an Actionscript 3 “Class” file. Without going into too deep into OOP concepts, I will attempt to explain how to implement an as3 class into your project. The following is a class for our example:

package com.frigidfish{
   
    import flash.display.Sprite;
   
    public class Monkey extends Sprite{
       
        private var currentState:String = "";
       
        public function Monkey(){
           
            trace('New Monkey Instance Created');          
        }
       
        public function set jumping(bool:Boolean){
           
            if(bool){
                trace('Monkey is jumping around!');
                currentState = "jumping";
                return;
            }          
        }
       
        public function get jumping():Boolean{
           
            if(currentState == "jumping"){
                return true;
            }
            return false;
        }      
    }
}

The first line is the location of the package. Generally developers will save their classes under a hierarchy that is their website name backwards.. in my case, my game projects are under my business name frigidfish.com so all of my actionscript classes are stored under com.frigidfish.

To clarify, lets start by opening flash and selecting File|New, Flash File (Actionscript 3) and click OK. Save the new file to your hard drive somewhere in a folder called “Monkey”.

Now, navigate to the Monkey folder and create a subfolder called “com”. Navigate to the com folder and create another subfolder called “frigidfish”.

Go back to Flash and click File|New. Select “Actionscript File” and choose OK.
You will get a blank page that you can enter code into. Paste the code from above into the blank page and save it in the newly created Monkey/com/frigidfish as Monkey.as

Now go back to the flash file we created first and open the “actions” panel by hitting the F9 key on a PC and on a mac I’m not sure, just click Window|Actions.

In the Actions panel you can start typing in code. The first thing you’ll want to do is import the class that we saved so that you can use it. Enter the following line:

import com.frigidfish.Monkey

Now that the class is available, we can create a new variable instance of it. You can think of a class file as a ‘prototype’. In this case it is a prototype of a Monkey… The cool thing about a class file is that you can make as many instances of it as you’d like.

Ok, so now enter the following line:

var silly:Monkey = new Monkey()

This line creates an instance of Monkey called silly. The Monkey class does not accept any arguments so we just leave the () empty. All classes have what is called a ‘constructor’ function. This is a public function that bears the same name as the class. Anything you put in the constructor function will be executed immediately when the class is instantiated. If the constructor does nothing, it is perfectly legal to leave it out of the class completely, but it is considered bad practice to do so.

In our case, the Monkey class constructor only has one line of code which just traces ‘New Monkey Instance Created’.

Go ahead and test the movie.

If you look in the output panel you will see that not much happens except that you receive the message about the new instance being created. Go ahead and close the test window.

add this line of code next:

trace(silly.jumping);

If you test the movie now, you will see that in addition to the new instance message, a new line appears that says ‘false’. The default jumping state of the monkey is false.

go ahead and add the next couple of lines:

silly.jumping = true;
trace(silly.jumping);

If you test the movie now, you should see the following:

New Monkey Instance Created
false
Monkey is jumping around!
true

Let’s go through this.

First we created a new instance of Monkey called silly.
Next we asked flash to display the jumping state of silly, which returned false.
Next we set silly’s jumping property to true, and he started jumping.
Last we ask flash to display the current jumping state of silly, which returned true.

So you should be able to see how to get started using classes with Actionscript 3. I also used a couple of getter and setter functions in the class. I will write an tutorial on this but for now a brief overview:

In Actionscript, you can set or get properties using functions. To the person setting the property, they are none the wiser that they are actually using a function.

In our example we simply set the monkey jumping with the statement:

silly.jumping = true;

in your class, if you create a function using the ‘set’ keyword, the function name will be treated as if it were a property. Likewise, the ‘get’ keyword can be used if a developer would like to retrieve the current value or state of a classes ‘property’.

It is important to note that the value passed to the setter function must be of the same data type that is returned from the getter function. Anyhow, I am getting off track but it’s all good information.

I Hope you find this useful in your quest to build more manageable Actionscript 3 projects!