Wednesday, February 11, 2009

BitmapData Transparency Masking

Have you ever wondered what the most efficient way to mask transparent areas in a bitmapdata is?
Well out of interest for my current engine I ran a small test on the 3 possible methods:

My results lead me to believe that threshold works best so far.

treshold time: 281 ms

copychannel time: 873 ms
merge time: 1162 ms

Here is the testclass I used:

package {

import flash.display.*;
import flash.geom.*;
import flash.ui.*;
import flash.utils.*;

public class MaskTest extends Sprite {

private var testBuffer:BitmapData;
private var displayBuffer:BitmapData;
private var maskBuffer1:BitmapData;
private var maskBuffer2:BitmapData;

public function MaskTest() {



private function init():void {

testBuffer = new BitmapData(200, 200, true, 0xFF000000);
displayBuffer = new BitmapData(200, 200, true, 0xFFFF0000);

maskBuffer1 = new BitmapData(200, 200, true, 0xFF000000);
maskBuffer1.fillRect(new Rectangle(50, 50, 100, 100), 0xFFFFFFFF);

maskBuffer2 = new BitmapData(200, 200, true, 0x00000000);
maskBuffer2.fillRect(new Rectangle(50, 50, 100, 100), 0xFFFFFFFF);

var bp1:Bitmap = new Bitmap(displayBuffer);
var bp2:Bitmap = new Bitmap(maskBuffer1);
var bp3:Bitmap = new Bitmap(maskBuffer2);

bp2.y = 200;
bp3.x = 200;
bp3.y = 200;



private function testThreshold(sourceBuffer:BitmapData, maskBuffer:BitmapData):void {
// mask black -> transparent white -> original value
sourceBuffer.threshold(maskBuffer, maskBuffer.rect, new Point(0, 0), "==", 0xFF000000, 0x00000000, 0xFFFFFFFF, false);

private function testCopyChannel(sourceBuffer:BitmapData, maskBuffer:BitmapData):void {
// copy alpha channel
sourceBuffer.copyChannel(maskBuffer, maskBuffer.rect, new Point(0, 0), BitmapDataChannel.ALPHA , BitmapDataChannel.ALPHA);

private function testMerge(sourceBuffer:BitmapData, maskBuffer:BitmapData):void {
// merge alphas to add transparency
sourceBuffer.merge(maskBuffer, maskBuffer.rect, new Point(0, 0), 0, 0, 0, 0xFF);

private function runTests():void {
var startTime:Number = 0;
var endTime:Number = 0;
var totalTime:Number = 0;
var numTests:uint = 1000;

startTime = getTimer();
var i:uint;
for(i = 0; i < numTests; i++){
testBuffer.copyPixels(displayBuffer, displayBuffer.rect, new Point(0, 0), null, null, false);
testThreshold(testBuffer, maskBuffer1);
endTime = getTimer();
totalTime = endTime - startTime;
trace("treshold time: "+totalTime);

startTime = getTimer();
for(i = 0; i < numTests; i++){
testBuffer.copyPixels(displayBuffer, displayBuffer.rect, new Point(0, 0), null, null, false);
testCopyChannel(testBuffer, maskBuffer2);
endTime = getTimer();
totalTime = endTime - startTime;
trace("copychannel time: "+totalTime);

startTime = getTimer();
for(i = 0; i < numTests; i++){
testBuffer.copyPixels(displayBuffer, displayBuffer.rect, new Point(0, 0), null, null, false);
testMerge(testBuffer, maskBuffer2);
endTime = getTimer();
totalTime = endTime - startTime;
trace("merge time: "+totalTime);


Sunday, February 08, 2009

Platformer Engine

The lightning model got tweaked some more and looks already a lot better now.
Another new addition are the fire and smoke particles, interactive objects (chairs, crates) that respond more or less to physics. Apart from that elevators, switches and doors were added.

In other words the engine is coming along pretty nicely. :)

See for yourself:

Tuesday, February 03, 2009

Static Lightning

Here is another example of the new lightning. Just to show how strong it can affect the outlook of normal tiles.

No Lightning on top, lightning activated on the bottom:

Monday, February 02, 2009

Whats happening lately...

I just noticed, that its about time to do another post on here. It's been half a year now without any news.

Anyways you might wonder what I have been upto all that time. Well appart from being really busy with studies, there are two new games waiting to be sponsored.

I created a small puzzle game called "Kilotron" to give it a shot on Flash Game License (FGL). Its a Bejeweled like puzzle game with a twist.

There was basically no serious interest by any sponsors in the game except for one. Hence I did a reskinning of the game which resulted in BubbleShells

Unfortunatelly, communication has been complicated and yet it is still waiting to be sponsored. Summing it up there are two versions of the game now featuring different designs but no sponsor. It is really sad considering the effort put into it.

Yet it was an experiment that did not go so well as for example Emanuele Ferronando's experiments.

Recovered from liking the wounds of wasted time, I finally got to do something more to my likings. I started working on my first plattformer engine.

After gathering a lot of inputs all over the web and getting enough inspiration I started setting up a prototype and then began working on the real thing.

Yet it is still unsure what features will be included and which will be dropped. A lot of things are in experimental stage.

So far I have set up a new kind of tile engine. It is a mixture of super tiles and regular tile engine combined with bitmap data manipulation. Nothing too fancy but just what is needed for my game.

There are some almost realistic physics plugged into it, ranging from ragdolls to other nifty IK things using verlet integration.

But what I am really proud of at the moment is the lightning. After some experiments and having to live with the fact that flash wont be able to handle dynamic lights and shadows at runtime, I had to do a step backwards to static lightning.

So basically the tiles can be lighted out and throw "softish" shadows. Every moving object will adapt to the environement lightning. Additionally an ambient lightning can be set to avoid the necessity of too many light sources all over the level.

Now the next goal is to bring in all interactive stuff as AI, graphics ect. And make some kind of game out of this basic engine. Hopefully the performance bottleneck wont force me to deactivate the lightning again. Fact is completely dynamic shadows would require hardware accelleration which there is none in flash at the moment.

That's about it for now. Stay tuned!