Archive for the ‘AS3’ Category

Merging Layered BitmapData in AS3

Thursday, February 14th, 2008

This tutorial is for those of your who might have to write your own Photo-shop-a-like applications or anyone who has to merge [flatten] two BitmapData together at pixel-level, without using BitmapData.copyPixels or BitmapData.merge. Furthermore this tutorial deals with bitwise operations, which are super fast and rad for color computation. Boom. Color. If you’re not familiar with bitwise operators I suggest you check out Polygonal Labs’ Bitwise Gems: Fast Integer Math. Done? Great. Okay, on with our discussion. I hope this stuff makes sense because this is my first tutorial. Ever…. …so first let’s create some colored Bitmaps on the page.

var bmd1:BitmapData = new BitmapData(100, 100, true, 0xFF00FF00);
var bm1:Bitmap = new Bitmap(bmd1);
addChild(bm1);
var bmd2:BitmapData = new BitmapData(100, 100, true, 0xFFFF0000);
var bm2:Bitmap = new Bitmap(bmd2);
bm2.y = bm1.height;
addChild(bm2);
var bmd3:BitmapData = new BitmapData(100, 100, true, 0x7F0000FF);
var bm3:Bitmap = new Bitmap(bmd3);
bm3.x = bm1.width/2;
bm3.y = bm1.height/2;
addChild(bm3);

Building our project we should see somethin like this:
MergingLayeredBitmapDataStep1
As you can see we’ve created a super green bmd, a bloody red bmd and a half-hearted (half-opaque) blue bmd. When the half-opaque blue bitmap is placed over the green and red bitmaps it filters the green and red bitmaps, altering the percieved colors. Our goal is to be able to calculate those percieved colors given two 32 bit colors in order to merge them onto a new BitmapData.

Now let’s begin our pixel layering function. We can start by outlining what the function is going to do. Let’s give it two 32 bit colors, (like the red and blue or the green and blue) and let’s make it give us back a 32 bit color that represents the two colors layered on top of each other.

private function layerColor32(topColor:uint, bottomColor:uint):uint
{
}

Now let’s extract each color’s ARGB channels. Traditionally the method would look like this:

private function layerColor32(topColor:uint, bottomColor:uint):uint
{
    var aB:uint = bottomColor >>> 24;
    var rB:uint = bottomColor >>> 16 & 0xFF;
    var gB:uint = bottomColor >>> 8 & 0xFF;
    var bB:uint = bottomColor  & 0xFF;
    var aT:uint = topColor >>> 24;
    var rT:uint = topColor >>> 16 & 0xFF;
    var gT:uint = topColor >>> 8 & 0xFF;
    var bT:uint = topColor  & 0xFF;
}

But since we’re working with what the colors *should* look like when layered, we have to figure out how much each channel actually shows through, according to the alpha channel. To do this we’ll multiply each channel by the color’s alpha channel’s opacity. The opacity is simply the alpha channel value divided by 255. So 100% opacity (255 or 0xFF) would turn out as 1, and 1 times each channel means 100% of each channel will show. 50% opacity (127 or 0x7F-0×80) would turn out as .5 and .5 times each channel shows 50% of each channel. Thus:

private function layerColor32(topColor:uint, bottomColor:uint):uint
{
    var aB:uint = bottomColor >>> 24;
    var rB:uint = (bottomColor >>> 16 & 0xFF)*(aB/0xFF);
    var gB:uint = (bottomColor >>> 8 & 0xFF)*(aB/0xFF);
    var bB:uint = (bottomColor  & 0xFF)*(aB/0xFF);
    var aT:uint = topColor >>> 24;
    var rT:uint = (topColor >>> 16 & 0xFF)*(aT/0xFF);
    var gT:uint = (topColor >>> 8 & 0xFF)*(aT/0xFF);
    var bT:uint = (topColor  & 0xFF)*(aT/0xFF);
}

Now that we have our individual channel values we can begin to calculate our new color. Remember that the maximum color value is 255 (0xFF) so we’ll be constraining our channel additions to 255.

private function layerColor32(topColor:uint, bottomColor:uint):uint
{
    var aB:uint = bottomColor >>> 24;
    var rB:uint = (bottomColor >>> 16 & 0xFF)*(aB/0xFF);
    var gB:uint = (bottomColor >>> 8 & 0xFF)*(aB/0xFF);
    var bB:uint = (bottomColor  & 0xFF)*(aB/0xFF);

    var aT:uint = topColor >>> 24;
    var rT:uint = (topColor >>> 16 & 0xFF)*(aT/0xFF);
    var gT:uint = (topColor >>> 8 & 0xFF)*(aT/0xFF);
    var bT:uint = (topColor  & 0xFF)*(aT/0xFF);

    var aN:uint = Math.min(aB + aT, 0xFF);
    var rN:uint = Math.min(rB + rT, 0xFF);
    var gN:uint = Math.min(gB + gT, 0xFF);
    var bN:uint = Math.min(bB + bT, 0xFF);
}

If you combine our channels and return the new color you’ll get something much brighter than what we should see. We’re going to have to filter the bottom color through the top color to fix this. You might be saying “ah man, I’ll just use BitmapData.copyPixels,” but don’t worry, we’re almost done. It’ll be so much more satisfying to figure out this stuff in the end, believe me. You’ll be a color scientist. So, all we need to do is multiply each channel of the bottom color by a number that represents how much light penetrates the top layer. So, if our top layer alpha channel is 0x7F, our ‘show through’ variable is going to be 50% (0x7F) and if our top alpha channel is 0×40 (25%) then 75% of the bottom channel will show through. To do this we’ll create our ‘show through’ var and multiply the bottom channels by it.

private function layerColor32(topColor:uint, bottomColor:uint):uint
{
    var aB:uint = bottomColor >>> 24;
    var rB:uint = (bottomColor >>> 16 & 0xFF)*(aB/0xFF);
    var gB:uint = (bottomColor >>> 8 & 0xFF)*(aB/0xFF);
    var bB:uint = (bottomColor  & 0xFF)*(aB/0xFF);
    var aT:uint = topColor >>> 24;
    var rT:uint = (topColor >>> 16 & 0xFF)*(aT/0xFF);
    var gT:uint = (topColor >>> 8 & 0xFF)*(aT/0xFF);
    var bT:uint = (topColor  & 0xFF)*(aT/0xFF);
    /*this determines how much of our lower layer shows through*/
    var showThru:Number = (0xFF - aT)/0xFF;
    trace("laryerColor32:showThru: (255 - "+aT+")/255 = "+showThru);
    /**********************************************************************/
    var aN:uint = Math.min(aB + aT, 0xFF);
    var rN:uint = Math.min(rB*showThru + rT, 0xFF);
    var gN:uint = Math.min(gB*showThru + gT, 0xFF);
    var bN:uint = Math.min(bB*showThru + bT, 0xFF);
}

Now for the last bit. Let’s combine all our new channels and return that value.

private function layerColor32(topColor:uint, bottomColor:uint):uint
{
    var aB:uint = bottomColor >>> 24;
    var rB:uint = (bottomColor >>> 16 & 0xFF)*(aB/0xFF);
    var gB:uint = (bottomColor >>> 8 & 0xFF)*(aB/0xFF);
    var bB:uint = (bottomColor  & 0xFF)*(aB/0xFF);
    var aT:uint = topColor >>> 24;
    var rT:uint = (topColor >>> 16 & 0xFF)*(aT/0xFF);
    var gT:uint = (topColor >>> 8 & 0xFF)*(aT/0xFF);
    var bT:uint = (topColor  & 0xFF)*(aT/0xFF);
    /*this determines how much of our lower layer shows through*/
    var showThru:Number = (0xFF - aT)/0xFF;
    trace("laryerColor32:showThru: (255 - "+aT+")/255 = "+showThru);
    /**********************************************************************/
    var aN:uint = Math.min(aB + aT, 0xFF);
    var rN:uint = Math.min(rB*showThru + rT, 0xFF);
    var gN:uint = Math.min(gB*showThru + gT, 0xFF);
    var bN:uint = Math.min(bB*showThru + bT, 0xFF);
   
    return(aN << 24 | rN << 16 | gN << 8 | bN);
}

Awesome! Were done. Using this function, for loops and some creativity, you can compile any number of 32 bit BitmapData on top of each other. Boom. Color. So, let’s use this function and compare it to the blending that happens within DisplayObjectContainers with transparency! Let’s alter our first bitmap generating/placing code to use our new function:

var bmd1:BitmapData = new BitmapData(100, 100, true, 0xFF00FF00);
var bm1:Bitmap = new Bitmap(bmd1);
addChild(bm1);
var bmd2:BitmapData = new BitmapData(100, 100, true, 0xFFFF0000);
var bm2:Bitmap = new Bitmap(bmd2);
    bm2.y = bm1.height;
addChild(bm2);
var bmd3:BitmapData = new BitmapData(100, 100, true, 0x7F0000FF);
var bm3:Bitmap = new Bitmap(bmd3);
    bm3.x = bm1.width/2;
    bm3.y = bm1.height/2;
addChild(bm3);
var color1:uint = bmd1.getPixel32(0, 0);
var color2:uint = bmd3.getPixel32(0, 0);
var color3:uint = layerColor32(color2, color1);
var color4:uint = bmd2.getPixel32(0, 0);
var color5:uint = layerColor32(color2, color4);
var bmd4:BitmapData = new BitmapData(50, 50, true, color3);
var bm4:Bitmap = new Bitmap(bmd4);
    bm4.x = bm1.width;
addChild(bm4);
var bmd5:BitmapData = new BitmapData(50, 50, true, color5);
var bm5:Bitmap = new Bitmap(bmd5);
    bm5.x = bm1.width;
    bm5.y = bm1.height*1.5;
addChild(bm5);

Let’s take a look at it.
MergingLayeredBitmapDataStep2
Wow, I don’t believe. Well, there you have it. Bust out your color schemer (or equivalent) and check those hex codes. Exact are they not? I hope you enjoyed this! Yay color.

AS3 Classes and Interfaces Quicktip

Saturday, January 19th, 2008

Interfaces in AS3 are super useful for requiring classes to support a set of public methods, enabling other classes to communicate through the interface thereby abstracting the class itself. AS3 doesn’t natively support abstract classes so using Interfaces is a good replacement in some cases, but if you’ve never used an Interface before you probably wouldn’t know how to implement it. The docs help a little, showing you how to instantiate a class using an interface with the “implements” keyword, but doesn’t go much further:

public class myClass implements myInterface{
}

But what if you’d like to implement a class while extending another? Well, it’s simple once you know the syntax…

public class myClass extends baseClass implements myInterface {
}

This is a very quick and simple tip that took me a while to find online due to the fact Adobe doesn’t mention it. Such a simple thing should be in the help docs, but I guess adobe thinks that anyone trying to use Interfaces would already know the syntax! Well now you do.

Joa Ebert SpeedCodes a Particle Explosionater [Explodinating the Countryside]

Tuesday, January 15th, 2008

I just like posting vidyos when I’m too lazy to code or write about code.

AS3 Window Class (real-time skinnable)

Wednesday, December 12th, 2007

[edit august 21st 2008] Hey guys this code is available but it is messy and the project has been scrapped. I will pick it up again, probably with OpenGL and C++[/edit]

In an effort to (maybe) find a new job, depending on what happens with my current one, I’m releasing a preview of my GUI classes. This class is a window class. It contains your display objects in a nice, draggable, scrollable and real-time skinnable window. You can make your own graphics for the window and configure button placement, scrollbar offsets, label, offsets and all other text goodies from an external config.xml script. There’s nothing to keep in your library and it’s not that big. It would be nice if anyone who uses it can tell me their memory stats, as I’m currently looking to make sure my code is clean and there are no leaks. Click the link below for a little demo.

Here’s the demo!

If you’re interested in using the class you can dive in headfirst at your own risk. It’s kinda long (about 1200 lines). I’ll be working on completely revising it from the ground up as it really is a big mess right now.

Source: GUI – mess

AS3 doLater/todo Function Queue

Saturday, December 8th, 2007

While working on my windowing system I ran into a problem. Every time I tried to set the width of my window class instance I’d get an error from my bitmap resource handler telling me the resources hadn’t been loaded. This makes it impossible to set widths for a window before it’s loaded, and since the entire system is supposed to be deployable online, loading time is not anything I can count on. I wrote this small class to take care of executing functions at a given time (like after loading is finished). The class is called Queue and here is some usage:

import com.efnx.utils.Queue;

function blah(val1:int, val2:int):void
{
    trace(val1+val2);
}

function blah2(val1:int, val2:int):void
{
    trace(val1+val2);
}

var queue:Queue = new Queue();
    queue.push(blah, 1, 5);
    queue.push(blah, 2, 5);
    queue.push(blah, 4, 5);
    queue.push(blah2, 3, 5);
   
   
trace(queue);

queue.start();

That code does this -> First we define two different functions, blah and blah2. Then we push the functions to be executed into the queue. Here’s the interesting part. Since the Dictionary Object inside the class used to list functions is not weakly referenced Duplicate entries cannot be made by the same function regardless of it’s parameters. In the the example above I push blah into the queue three times, but the only one that fires and traces is the third because the queue’s key is the function itself [or the "closure object (ie. the "behind the scenes" object that facilitates method closure by maintaining a reference back to the method and its scope)" as described by Grant Skinner], so the function replaces itself in the queue. This is nice for doing things like setting widths and resizing, although not so great for things like sending different strings to some handler. As of now calling start() applies the functions asynchronously and nullifies anything left in the queue. You’ll see the output traces this:

object [Queue]
->  function Function() {}  3,5
->  function Function() {}  4,5
8
9

First it traces the Queue Object which contains references to the two functions and their parameters (not in the order we gave them) then the output. Bam! Done. Oops! Not quite… …At any point you can flush the queue without executing the functions by calling abort(). There, done.

This class can be easily extended or modified to include directives to execute functions in a given order or multiple entries of one function, so get crackin!

Source
Queue Class Source Code

AS3 Bitmap Resource Manager

Saturday, December 1st, 2007

I’m now using a new class for this task which can be found here. That said, feel free to read on about this outdated class.

I’ve completely rewritten my multiple bitmap loader into a new machine. It now uses weak referenced dictionary objects to store bitmapData after it has been extracted or loaded from the web. It is meant to hold all instances of bitmapData for a class, a set of classes or a whole game even. The class, bitmapDataRsrc, takes either a bitmap, bitmapData or string path to an image or an array consisting of either bitmaps, bitmapData, string paths, or some combination thereof, along with a string identifier and loads the bitmapData into a dictionary object with it’s identifier as a key. It then pushes it’s load status [true or false] into another dictionary with the object itself as the key, so every bitmapData resource and it’s load status is accessible through the identifier. Once every resource is loaded bitmapDataRsrc dispatches an Event.COMPLETE event. For instance, let’s say I wanted to load and store all the bitmapData needed to build a GUI window:

import com.efnx.utils.bitmapDataRsrc;

var rsrc:bitmapDataRsrc = new bitmapDataRsrc();

rsrc.addEventListener(Event.COMPLETE, attachGraphicElements, false, 0, true);

//load resources///////////////////////
    rsrc.load("rsrc2/bottomBar.png", "bottomBar");
    rsrc.load("rsrc2/contentBG.png", "contentBG");
    rsrc.load("rsrc2/contentOverlay.png", "contentOverlay");
    rsrc.load("rsrc2/leftArrowDown.png", "leftArrowDown");
    rsrc.load("rsrc2/leftArrowOver.png", "leftArrowOver");
    rsrc.load("rsrc2/leftArrowUp.png", "leftArrowUp");
    rsrc.load("rsrc2/upArrowDown.png", "upArrowDown");
    rsrc.load("rsrc2/upArrowOver.png", "upArrowOver");
    rsrc.load("rsrc2/upArrowUp.png", "upArrowUp");
    rsrc.load("rsrc2/rightArrowDown.png", "rightArrowDown");
    rsrc.load("rsrc2/rightArrowOver.png", "rightArrowOver");
    rsrc.load("rsrc2/rightArrowUp.png", "rightArrowUp");
    rsrc.load("rsrc2/downArrowDown.png", "downArrowDown");
    rsrc.load("rsrc2/downArrowOver.png", "downArrowOver");
    rsrc.load("rsrc2/downArrowUp.png", "downArrowUp");
    rsrc.load("rsrc2/leftBar.png", "leftBar");
    rsrc.load("rsrc2/leftBottomCorner.png", "bottomLeftCorner");
    rsrc.load("rsrc2/MbuttonDown.png", "MbuttonDown");
    rsrc.load("rsrc2/MbuttonOver.png", "MbuttonOver");
    rsrc.load("rsrc2/MbuttonUp.png", "MbuttonUp");
    rsrc.load("rsrc2/ObuttonDown.png", "ObuttonDown");
    rsrc.load("rsrc2/ObuttonOver.png", "ObuttonOver");
    rsrc.load("rsrc2/ObuttonUp.png", "ObuttonUp");
    rsrc.load("rsrc2/resizeDown.png", "resizeDown");
    rsrc.load("rsrc2/resizeOver.png", "resizeOver");
    rsrc.load("rsrc2/resizeUp.png", "resizeUp");
    rsrc.load("rsrc2/rightBar.png", "rightBar");
    rsrc.load("rsrc2/rightBottomCorner.png", "bottomRightCorner");
    rsrc.load("rsrc2/hBarLeft.png", "hBarLeft");
    rsrc.load("rsrc2/hBarMiddle.png", "hBarMiddle");
    rsrc.load("rsrc2/hBarRight.png", "hBarRight");
    rsrc.load("rsrc2/vBarBottom.png", "vBarBottom");
    rsrc.load("rsrc2/vBarMiddle.png", "vBarMiddle");
    rsrc.load("rsrc2/vBarTop.png", "vBarTop");
    rsrc.load("rsrc2/windowBarLeft.png", "upperLeftCorner");
    rsrc.load("rsrc2/windowBarMiddle.png", "topBar");
    rsrc.load("rsrc2/windowBarRight.png", "upperRightCorner");
    rsrc.load("rsrc2/XbuttonDown.png", "XbuttonDown");
    rsrc.load("rsrc2/XbuttonUp.png", "XbuttonUp");
    rsrc.load("rsrc2/XbuttonOver.png", "XbuttonOver");

After the resources are done loading you can access the bitmapData using the get() function with the string identifier [2nd parameter] passed with the load() function. Below I’ll demonstrate accessing the last bitmapData, XbuttonOver.png.

function attachGraphicElements(event:Event):void
{
     var bitmap:Bitmap = new Bitmap();
     bitmap.bitmapData = rsrc.get("XbuttonOver");
     addChild(bitmap);
}

If you get lazy and decide not to give bitmapDataRsrc string identifiers to identify your resource, it will make one up for you. If you decide to pass an array of bitmaps, bitmapData and string paths to images as the first parameter to the load() function, and pass a string identifier as the second parameter your resources will be indexed as “string identifier + number” so that all your resources are accessible. When passing an array of resources you can identify each one yourself by first indexing the resource and string identifier in another array and then pushing that array into the parameter array. In this case a second parameter to the load function is not needed. Check it out:

import com.efnx.utils.bitmapDataRsrc;

var rsrc:bitmapDataRsrc = new bitmapDataRsrc();
var array:Array;
var string:String;

for(var i:int = 0; i<100; i++)
{
    string = "image"+i;
    array = new Array();
    array.push("rsrcPath"+string+".png", string);
}

rsrc.load(array);

I find it a lot easier to load resources one by one and name them, it’s a lot better for me, I like to get to know my bitmapData, but it’s good to have options.

The isLoaded property can be checked to find out if all resources have loaded. At any point the load status of a single resource can be found by calling the hasLoaded(“string identifier”):Boolean function. If no identifier is given bitmapDataRsrc returns it’s isLoaded property. To destroy a given resource call unload(“string identifier”) and to destroy all resources in the manager call unloadAll():

trace(rsrc.isLoaded);
trace(rsrc.hasLoaded("XbuttonOver");
rsrc.unload("XbuttonOver");
rsrc.unloadAll();

Source
bitmapDataRsrc Source

Quake for Flash (C/C++ to AS3)

Tuesday, November 27th, 2007

Scott Peterson has created a tool for porting C/C++ code to AS3. What the shit. That rocks. This demo was shown at the 2007 Adobe MAX conference, in the sneak peeks section, so keep in mind it may never see the light of day. But how cool is this? Adobe better jump on this.

AS3 Button Class

Sunday, November 25th, 2007

This class has been updated and a new post has been made, click here for that post.

Also known as “Developing a Pure AS3 GUI – Part 2 (buttons)”

Buttons are extremely important in a GUI. Buttons don’t have to be fancy to be useful, they just have to execute some function when clicked. Although, seeing as this is a button class for AS3 and AS3 is the language of Flash and Flash is by it’s namesake, “flashy,” this class is somewhat “fancy” beyond the utility of a simple button. Don’t be discouraged if you’re looking for an easy implementation, by no means is this class complicated, it just goes further than binding a Sprite to a function using a CLICK event listener…

My button class requires three images to function: an “up” image [the default resting image], an “over” image [the image shown on mouse over] and a “down” image [the image shown when clicked upon]. After creating the three images and placing them in some directory next to your .fla you can instantiate the button by giving it an array consisting of three image paths that lead to your images. Additional parameters are a function to be performed on click and whether or not the button is a toggle button.

Usage

var myButton:button = new button(new Array("image1.png", "image2.png", "image3.png"), onClick, false);
     addChild(myButton);

function onClick():void
{
     trace("button has been clicked");
}

And that’s it. If you’d like the button to run in toggle mode just pass true as the third parameter.

Source
button Class Source Code

Multiple Bitmap Loader in AS3

Sunday, November 25th, 2007

To aid in my projects I have written a simple bitmapData loading class entitled aquireResources. This class takes an array of image paths as strings and proceeds to load them one by one. A “complete” event is dispatched when loading is completed and the bitmapData of each loading instance are saved in an array in the order they were given. Calling the aquireResources.array() method returns the array of bitmapData. If you’ve already downloaded Thibault Imbert (bytearray.org)’s GIFPlayer and GIFDecoder classes you can uncomment the included properties and methods in my class and enable the aquireResources class to load multiple instances of animated GIFs into AS3 as arrays of bitmapData. In this case aquireResources.array() returns a two-dimensional array containing one array of bitmapData per animated GIF passed to it.

Usage

import com.efnx.utils.aquireResources;

var rsrc:aquireResources = new aquireResources();
     rsrc.addEventListener("complete", onComplete, false, 0, true);

var array:Array = new Array("imagePath1/image1.png", "imagePath2/image2.gif", "imagePath3/image3.jpeg");
var bitmapDataArray:Array;
function onComplete(event:Event):void
{
     bitmapDataArray = rsrc.array();
}

rsrc.aquireImages(array);

For loading animated GIFs

import com.efnx.utils.aquireResources;

var rsrc:aquireResources = new aquireResources();
     rsrc.addEventListener("complete", onComplete, false, 0, true);

var array:Array = new Array("imagePath1/image1.gif", "imagePath2/image2.gif", "imagePath3/image3.gif");

var animatedArray:Array;
function onComplete(event:Event):void
{
     animatedArray = rsrc.array();
}

rsrc.aquireGIFs(array);

Source
aquireResources Source

Simple Tiling Sprite Class in AS3

Monday, November 19th, 2007

Also known as “Developing a Pure AS3 GUI – Part 1.5 (tile)
Jump to Source
After writing last night’s class, scalingBars, I decided to make it a little easier on myself to tile bitmaps across the screen. I wrote a simple class that when given either a BitmapData object or a path to an image file (as a String), class will tile the image x pixels in width and y pixels in height. This is great for backgrounds or window bars or box sides, etc. Here’s the usage:

var bar:tile = new tile("pathToImageOrBitmapDataObject", 100, 150);
     addChild(bar);

The previous code will grab an image from “pathToImage” [either relative or absolute, but remember security!] and then tile it 100 pixels wide by 150 pixels tall. Simple. Now let’s say you wanted to resize it:

bar.resize(20, 40);

That code will re-tile the image to 20 pixels by 40 pixels. Next on my list of upgrades is to allow reloading of different images. Shouldn’t be too hard.
Example

Source
tile Class Source Code


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