Archive
This post is archived and may contain outdated information. It has been set to 'noindex' and should stop showing up in search results.
This post is archived and may contain outdated information. It has been set to 'noindex' and should stop showing up in search results.
ActionScript 3 Semi-Transparent CopyPixels
May 31, 2011ProgrammingComments (0)
When working with BitmapData and copyPixels, you'll quickly run into the limitation of not having an alpha attribute with which to change the transparency level of objects. If you're like me, you started out using Sprite and MovieClip in your games and could easily fade-in or fade-out objects using the alpha attribute. Unfortunately, BitmapData does not have the alpha attribute, so how do you adjust transparency dynamically while using copyPixels?
You could create several versions of every image at different transparency levels. This is very tedious and will result in more file size and memory usage. Another way is to use a separate transparent BitmapData mask and apply it to any image that you want transparent.
CopyPixels has three optional arguments: alphaBitmapData, alphaPoint and mergeAlpha (see Adobe docs for the full argument details). What these do is allow you to apply the transparency of one BitmapData to another. So you can, for example, create an array of BitmapData objects, each at varying degrees of transparency (how to create semi-transparent BitmapData objects). With this array, you can apply different levels of transparency to any other image, fade-in or fade-out, and smoothly adjust transparency. Just make sure the dimensions of your transparent BitmapData objects are large enough to encompass any of the images you intend to use.
I should note that using this method will incur a small performance hit, and it may actually be faster in terms of process time to just make multiple versions of every image with different transparency levels.
These are the images I will be using for this example:
First, here is a basic method for drawing the tank onto the background using copyPixels:
The result:
Now to add a semi-transparent BitmapData and merge it with the tank:
The result:
I left the alphaPoint argument as null because I didn't need to adjust where the transparent BitmapData object overlapped the tank.
Using alphaMerge, you can create some useful effects with copyPixels.
Here is how you might go about making the tank fade out:
What the above does is create an array of transparent BitmapData objects, in steps of 10% transparency. You can create each BitmapData manually if you want (I have a chart of hex values and their base-10 equivalents in steps of 10 at the bottom of this post).
I find it easier to use the loop.
With the BitmapData transparent array, each time the tank is drawn to the stage, it uses a more transparent BitmapData object from the array to merge with.
One last thing: In real-world usage, you wouldn't want to be instantiating new Points every frame. Instead, create them at the start and just reuse them.
You could create several versions of every image at different transparency levels. This is very tedious and will result in more file size and memory usage. Another way is to use a separate transparent BitmapData mask and apply it to any image that you want transparent.
CopyPixels has three optional arguments: alphaBitmapData, alphaPoint and mergeAlpha (see Adobe docs for the full argument details). What these do is allow you to apply the transparency of one BitmapData to another. So you can, for example, create an array of BitmapData objects, each at varying degrees of transparency (how to create semi-transparent BitmapData objects). With this array, you can apply different levels of transparency to any other image, fade-in or fade-out, and smoothly adjust transparency. Just make sure the dimensions of your transparent BitmapData objects are large enough to encompass any of the images you intend to use.
I should note that using this method will incur a small performance hit, and it may actually be faster in terms of process time to just make multiple versions of every image with different transparency levels.
These are the images I will be using for this example:
First, here is a basic method for drawing the tank onto the background using copyPixels:
var bg:BitmapData = new BG(248, 75);
var tank:BitmapData = new Tank(100, 75);
bg.copyPixels(tank, tank.rect, new Point(70, 90));
addChild(new Bitmap(bg));
The result:
Now to add a semi-transparent BitmapData and merge it with the tank:
var bg:BitmapData = new BG(227, 172);
var tank:BitmapData = new Tank(100, 60);
var alpha50:BitmapData = new BitmapData(300, 300, true, 0x7FFFFFFF);
bg.copyPixels(tank, tank.rect, new Point(70, 90), alpha50, null, true);
addChild(new Bitmap(bg));
The result:
I left the alphaPoint argument as null because I didn't need to adjust where the transparent BitmapData object overlapped the tank.
Using alphaMerge, you can create some useful effects with copyPixels.
Here is how you might go about making the tank fade out:
var scene:BitmapData = new BitmapData(550, 400, false, 0xFFFFFF);
var bg:BitmapData = new BG(227, 172);
var tank:BitmapData = new Tank(100, 60);
var tankalpha:int = 10;
var arr:Array = [];
for(var i:int = 0; i < 10; i ++)
{
arr[i] = new BitmapData(220, 220, true, i * 25 * 0x01000000);
}
addChild(new Bitmap(scene));
addEventListener(Event.ENTER_FRAME, framehandler);
function framehandler(e:Event):void
{
scene.copyPixels(bg, bg.rect, new Point(0, 0));
if(tankalpha > 0)
{
scene.copyPixels(tank, tank.rect, new Point(70, 90), arr[tankalpha], null, true);
tankalpha --;
}
}
What the above does is create an array of transparent BitmapData objects, in steps of 10% transparency. You can create each BitmapData manually if you want (I have a chart of hex values and their base-10 equivalents in steps of 10 at the bottom of this post).
I find it easier to use the loop.
With the BitmapData transparent array, each time the tank is drawn to the stage, it uses a more transparent BitmapData object from the array to merge with.
One last thing: In real-world usage, you wouldn't want to be instantiating new Points every frame. Instead, create them at the start and just reuse them.