Posts Tagged ‘FPS’

New Updated Tools/Classes For Actionscript 3

Monday, August 18th, 2008

Button
Calculating Frames Per Second [and memory usage]
MultiLoader
Example and Project Source

I’ve created a number of tools for people to use in the past, most of which I update regularly. In this post I’d like to revisit some of my old classes and post new updated code for those classes, as in their current form they don’t much represent my coding style. Please note that my class hierarchy has also changed, so make sure to update your includes if you are using these in your projects.

Button
I posted code for a button class here ->here about a year ago, since then I’ve changed things and really cleaned up that class. It’s simpler than before and faster. Given one to three images this class will create a clickable button that has the option to trigger up to four functions [on roll over, mouse down, mouse up and roll out]. Here is a snippet showing its use:

        var button:Button = new Button();
       
        // bitmapData of buttons "up" state
        var bmd_up:BitmapData = new BitmapData(50, 20, true, 0xFFBDE052);
        // bitmapData of buttons "over" state
        var bmd_over:BitmapData = new BitmapData(50, 20, true, 0xFF52C4E0);
        // bitmapData of buttons "down" state
        var bmd_down:BitmapData = new BitmapData(50, 20, true, 0xFFFFAF1A);
       
        button.x = 20;
        button.y = 20;
        // we pass our bitmapData to the button, one for each state. if only one bitmapData is supplied, it will be
        // copied to each state, after which each new bitmapData supplied will replace the first for the state
        // specified.
        button.up = bmd_up;
        button.over = bmd_over;
        button.down = bmd_down;
       
        // we supply functions to the buttons function references, if no functions are supplied, no functions will be called.
        button.overFunction = function():void{trace("UpdatedTools::UpdatedTools()", "button over");};
        button.downFunction = function():void{trace("UpdatedTools::UpdatedTools()", "button down");};
        button.upFunction = function():void{trace("UpdatedTools::UpdatedTools()", "button up");};
        button.outFunction = function():void{trace("UpdatedTools::UpdatedTools()", "button out");};
       
        addChild(button);
       
        // adding a label is as simple as creating a textfield and adding it to the button.
        var label:TextField = new TextField();
            label.textColor = 0xDDD4F7;
            label.mouseEnabled = false;
            label.text = "Button";
            label.autoSize = "left";
            label.x = button.width/2 - label.width/2;
            label.y = button.height/2 - label.height/2;
           
        button.addChild(label);

Calculating Frames Per Second
The next class I’d like to revisit is my FPS counter. It’s basically a textfield that displays an instantaneous fps count, and an averaged count. I have now removed the average frames per second and included a display of used memory in MB. Before I had used a timer to calculate the fps, which wasn’t quite accurate enough. Now the class uses flash.utils.getTimer() and is very precise and accurate. The class extends TextField so custom coloring, etc is very straightforward:

        var fps:FPSBox = new FPSBox();
        addChild(fps);

MultiLoader and MultiLoaderEvent
The next entry is a class created for downloading and importing files from your server or local file system into your flash application. It is what I use in place of my Multiple Bitmap Loader and my Bitmap Resource Handler. MultiLoader extends Loader to support multiple asynchronous downloads of images/swfs. They trigger specific (read “specially named”) ProgressEvents based on the names of entries supplied by you in their load functions. Alternatively, they also trigger a MultiLoaderEvent for every ProgressEvent or complete Event dispatched. One can access the bytesLoaded and bytesTotal for each event, as well as the entry name of the event (which matches the entry name given to MultiLoader). For example, to load a gif and listen to progress and complete events, code the following:

        var multiLoader:MultiLoader = new MultiLoader();
            multiLoader.load("http://www.efnx.com/images/experiment.gif", "efnx");
                       multiLoader.load("http://www.efnx.com/images/experiment.gif", "efnx", "Bitmap");
            multiLoader.addEventListener("efnx_Progress", efnxProgress, false, 0, true);// specially named
            multiLoader.addEventListener("efnx_Complete", efnxComplete, false, 0, true);// specially named
               multiLoader.addEventListener("progress", progress, false, 0, true);// will trigger a MultiLoaderEvent with an entry member for identification
               multiLoader.addEventListener("complete", complete, false, 0, true);

    private function efnxProgress(event:ProgressEvent):void
    {
        trace("UpdatedTools::efnxProgress()", (event.bytesLoaded/event.bytesTotal*100));
    }
    private function efnxComplete(event:ProgressEvent):void
    {
        trace("UpdatedTools::efnxComplete()");
    }
    private function progress(event:MultiLoaderEvent):void
    {
        trace("UpdatedTools::progress()", event.entry, (event.bytesLoaded/event.bytesTotal*100));
    }
    private function complete(event:MultiLoaderEvent):void
    {
        trace("UpdatedTools::complete()", event.entry);
    }

In this example my entry name is “efnx” and so MultiLoader triggers events of type “efnx_Progress” and “efnx_Complete”. By listening for these events, we can get updated information about our downloads. Another option is to listen for “progress” and “complete,” which will trigger an event of type MultiLoaderEvent, which extends ProgressEvent to include an “entry” member. The value of event.entry will be the name of the entry triggering the event, in this case “efnx.” Now to use our images we “get” the resource from MultiLoader, which has been storing it for us. A great feature of this class is being able to specify what the return type of your loaded object when calling the “get” function. Here I’m going to want to return a Bitmap object, so for the third parameter of the “load” function I’ll pass the string “Bitmap”. Here’s an example:

multiLoader.load("http://www.efnx.com/images/experiment.gif", "efnx", "Bitmap");

Now inside my efnxComplete function I’ll add the get function to get my Bitmap and display it.

        // if we are listening for "efnx_Complete"
    private function efnxComplete(event:Event):void
    {
        trace("UpdatedTools::efnxComplete()");
        var efnxBitmap:Bitmap = multiLoader.get("efnx");
            efnxBitmap.x = button.x + button.width + 10;
            efnxBitmap.y = button.y;
        addChild(efnxBitmap);
    }
        // or if we are listening for "complete"
    private function complete(event:MultiLoaderEvent):void
    {
        trace("UpdatedTools::complete()");
        var efnxBitmap:Bitmap = multiLoader.get(event.entry);
            efnxBitmap.x = button.x + button.width + 10;
            efnxBitmap.y = button.y;
        addChild(efnxBitmap);
    }

Using the third parameter of the load() function is optional and if omitted Multiloader will by default choose an appropriate return type, here is a list of the valid strings to pass as a return type:

MovieClip
Sprite
Bitmap
BitmapData

If no third parameter is supplied, MultiLoader will return a type it thinks is appropriate, given the extension of the loaded material. For example loading a .swf will return a MovieClip, where as loading a .jpeg, .png or .gif will return a BitmapData.

Example App and Project Source
Here is a project that shows all three updated classes being used:

package {

    import flash.events.Event;
    import flash.events.ProgressEvent;
    import flash.display.Sprite;
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.text.TextField;
   
    import efnx.gui.Button;
    import efnx.time.FPSBox;
    import efnx.net.MultiLoader;
    import efnx.events.MultiLoaderEvent;
   
/**
 *  Application entry point for UpdatedTools post.
 *
 *  @langversion ActionScript 3.0
 *  @playerversion Flash 9.0
 *
 *  @author Schell Scivally
 *  @since 18.08.2008
 */

public class UpdatedTools extends Sprite {
   
    public static const testing:Boolean = false;
   
    public var button:Button = new Button();
    public var multiLoader:MultiLoader = new MultiLoader();
   
    /**
     *  @constructor
     */

    public function UpdatedTools()
    {
        super();

        stage.frameRate = 30;
        stage.scaleMode = "noScale";
        stage.align = "TL";
        stage.addEventListener("resize", resize, false, 0, true);
       
        // bitmapData of buttons "up" state
        var bmd_up:BitmapData = new BitmapData(50, 20, true, 0xFFBDE052);
        // bitmapData of buttons "over" state
        var bmd_over:BitmapData = new BitmapData(50, 20, true, 0xFF52C4E0);
        // bitmapData of buttons "down" state
        var bmd_down:BitmapData = new BitmapData(50, 20, true, 0xFFFFAF1A);
       
        button.x = 20;
        button.y = 20;
        // we pass our bitmapData to the button, one for each state. if only one bitmapData is supplied, it will be
        // copied to each state, after which each new bitmapData supplied will replace the first for the state
        // specified.
        button.up = bmd_up;
        button.over = bmd_over;
        button.down = bmd_down;
       
        // we supply functions to the buttons function references, if no functions are supplied, no functions will be called.
        button.overFunction = function():void{trace("UpdatedTools::UpdatedTools()", "button over");};
        button.downFunction = function():void{trace("UpdatedTools::UpdatedTools()", "button down");};
        button.upFunction = function():void{trace("UpdatedTools::UpdatedTools()", "button up");};
        button.outFunction = function():void{trace("UpdatedTools::UpdatedTools()", "button out");};
       
        addChild(button);
       
        // adding a label is as simple as creating a textfield and adding it to the button.
        var label:TextField = new TextField();
            label.textColor = 0xDDD4F7;
            label.mouseEnabled = false;
            label.text = "Button";
            label.autoSize = "left";
            label.x = button.width/2 - label.width/2;
            label.y = button.height/2 - label.height/2;
           
        button.addChild(label);
       
        var fps:FPSBox = new FPSBox();
        addChild(fps);
       
        MultiLoader.testing = true;
        MultiLoader.usingContext = true;
       
        multiLoader.load("http://www.efnx.com/images/experiment.gif", "efnx", "Bitmap");
        multiLoader.load("http://www.efnx.com/images/808.jpg", "808", "Sprite");
        multiLoader.addEventListener("progress", progress, false, 0, true);
        multiLoader.addEventListener("complete", complete, false, 0, true);
    }
   
    private function progress(event:MultiLoaderEvent):void
    {
        trace("UpdatedTools::progress()", event.entry, ": ", (event.bytesLoaded/event.bytesTotal*100));
    }
    private function complete(event:MultiLoaderEvent):void
    {
        trace("UpdatedTools::complete()");
        switch(event.entry)
        {
            case "efnx":
                var efnxBitmap:Bitmap = multiLoader.get("efnx");
                    efnxBitmap.x = button.x + button.width + 10;
                    efnxBitmap.y = button.y;
                addChild(efnxBitmap);
                break;
            case "808":
                var sprite808:Sprite = multiLoader.get("808");
                    sprite808.x = button.x;
                    sprite808.y = button.y + button.height + 20;
                addChild(sprite808);
                break;
            default:
        }
    }
   
    /**
     *  Resize stub.
     */

    private function resize(event:Event):void
    {
        if(testing) trace( "UpdatedTools::resize()" );
    }
   
}

}

And here is the source to my classes:
Example Project and Source [includes classes]

Here is a little example:
updatedExample

And as always you can find the classes by themselves [along with all my other classes] here efnx AS3 classes, as well as some limited documentation efnx Class Documentation

AS3 – Calculating true Frames Per Second

Monday, October 22nd, 2007

I strongly recommend you look at this new version of this class.

When coding for Flash based games it’s important to know how fast your project is running [even if you're not coding games it's good to know whether or not your code is slogging down the player]. Adobe’s Stage class provides a parameter called “frameRate,” which allows you to dynamically get and set the player’s frame rate. Well, not exactly. It allows you to get and set the player’s TARGET frame rate, the fact is if the player can’t perform your code at that frame rate, it won’t! So how can you find out what the real frame rate is?

I wrote a simple class for this task to use in my project development. It’s super simple. My class, fpsBox, adds an eventListener to the stage [if you pass the stage as an argument when instantiating the class] or to itself, that triggers every frame and increments a value. A timer is started simultaneously with a repeat cycle of one second. Every second the number of counts counted each frame are displayed in the fpsBox and then averaged in an array of instantaneous values. Don’t worry, the array never gets past two values, the current average and the instantaneous FPS. Here’s some usage:

import com.efnx.fps.fpsBox;

var fps:fpsBox = new fpsBox(stage);
     addChild(fps);

That’s it!

What it looks like:

Link to SWF

Source Code
fpsBox Class Source Code

AS3 Animation class to replace MovieClip

Monday, October 15th, 2007

Okay, let me start by saying that I HATE importing resources into fla’s. When I first learned Flash [AS2] it wasn’t an issue. Now with AS3 and the necessity of classes my coding style has changed and I really, really like keeping things as separated into classes as possible.

The Problem With MovieClips
When attempting to program button classes I ran into this wall: Flash’s MovieClip is the only appropriate class object to use for animation. It’s great for placing images in your timeline to form moving pictures and placing Actionscript on certain frames makes directing the clip around really easy. But what about when you have to make MovieClips dynamically and add code to certain frames inside that clip, without using the GUI? MovieClip doesn’t support dynamically adding frames, or functions or Bitmaps to certain frames. This sucks. Why Adobe did this I do not know – so I wrote a class that DOES WHAT I WANT [and maybe you too].

Usage
Animation takes three parameters, which are all optional: numFrames:int = 1 width:int = 0, and height:int = 0. These params just initiate the object.

/*
*     blog.efnx.com:Animation Example
*/


import com.efnx.utils.Animation;     //import the class

var character:Animation = new Animation();     //object sets numFrames, width and height to 1, 0 and 0

After making the object you have to append the pictures to certain frames using the appendBitmapData function:

character.appendBitmapData(theFrame:int, bitmapData:BitmapData);

What this does is take the BitmapData and attach a function to the given frame that replaces the Animation’s default BitmapData with yours upon execution of that frame.
Doing this achieves the same effect as dragging a bitmap onto the stage in a MovieClip keyframe.

I wrote the class keeping in mind that someone may want to use it not for animation but sequential code execution, so frames can be created and functions attached to each frame without any graphics associated. The function used to add [or append] other functions to a certain frame is

     appendFrameScript(theFrame:int, theFunction:Function, [testing:Boolean = false]);

theFrame is the frame you’d like to add a function to, theFunction is the function to be added and testing tells the class whether or not to print debug info.

After adding frames and bitmaps and all that Animation can be controlled using familiar MovieClip methods like gotoAndPlay(), gotoAndStop(), go(), stop() and properties like currentFrame and totalFrames, as well as some others – bmd [the current frames BitmapData], bmdArray [an array of all frames BitmapData] and cool functions like customFps(fps:int) which set a custom playback rate denoted in number of frames per second [fps:int] and accelerateFps(desiredFps:int, numberFrames:int) which accelerates the playback delay from the current FPS to the desired FPS in numberFrames frames. accelerateFps is still a little buggy, feel free to nice it up!

Last Words
Animation doesn’t automatically loop your animation [since I usually don't need it to], so to really mimic a MovieClip you’d have to write a function incorporating gotoAndPlay(1) and then attach the function to the frame you’d like to loop your clip at:

var character:Animation = new Animation();                   //initiate object
     character.appendBitmapData(1, firstBitmapData);       //add BitmapData
     character.appendBitmapData(2, secondBitmapData);
     character.appendFrameScript(2, repeat);                   //append repeat function

function repeat():void                //repeat function
{
     character.gotoAndPlay(1);
}

Hope this class helps some of you out. Feel free to let me know what needs improving and comment if you like it!

Source
Animation Class Source Code


Follow me on GitHub
Follow me on Google+
Follow me on Twitter