Imagine you want to code a raycaster or any l33t oldschool effect. What you need is direct pixel-access (ok, not really for the raycaster).
Now there is the problem which method could be used. image.setPixel for every pixel or image.setPixels.
Now some people talk about using setPixel because it is faster. This is something I can not understand, because for me the ByteArray was everytime a little bit faster.
I searched for problems using the ByteArray and even in some cases it seemd to me that the setPixel method is faster.
About how I tested the speed: I used a simple oldschool plasma for the speed comparison and tried differend methods to fill the image and also to store the palette.
Do not store colors / data in a ByteArray
Yes. For a plasma you can create a color palette. I used a simple Array and a ByteArray.
All colors are precached so the only thing I tried to optimize was the real data.
In the first test I used a ByteArray with 3 bytes per color. When the color was extracted I had to do this:
[as]pos = ((plasma[ x ][ y ] + paletteShift) % 256) * 3;
s.setPixel( x, y, (palette[ pos ] < < 16) | (palette[ pos + 1 ] << 8) | palette[ pos + 2 ] );[/as]
Of course the data which is stored in the memory is n * 1 byte less but putting all the values together slows flash down.
The next test has been made with a ByteArray that used 4 bytes for every color which was a little bit faster. Using setPixel( x, y, palette.readUnsignedByte() ) saves you two times you would have to acces the ByteArray.
Now the fastest method I could discover:
Use an Array to store values. You are able to precalculate the whole color and the access is faster than using a ByteArray. I stored all colors using (r < < 16) | (g << 8) | b and this is the fastest method I could discover.
Now we want a method to fill the screen. On the one hand there is setPixel on on the other hand there is setPixels. In the test environment I used only one BitmapData which represents the whole screen.
Use a ByteArray as a buffer. Yes, it is faster. Only a little bit but it is faster. But be careful! Do not use direct acces like with the brackets. Use buffer.writeUnsignedInt() because this seemed to be the fastest method.
Using screen.setPixel() is not much slower but a little bit. Both functions I used here in comparison
[as]while ( x > 0 )
{
x–;
while ( y > 0 )
{
y–;
buffer.writeUnsignedInt( palette[ ((plasma[ x ][ y ] + paletteShift) % 256) ] );
screen.setPixel( x, y, palette[ ((plasma[ x ][ y ] + paletteShift) % 256) ] );
}
y = 128;
}[/as]
The other thing is const and var. No difference in the speed here. I like to define my screen and buffer as a const because I do not want to change them later on. This is how I did the tests:
[as]package
{
import flash.display.Sprite;
import flash.display.BitmapData;
import flash.display.Bitmap;
import flash.geom.Rectangle;
import flash.util.ByteArray;
import flash.events.Event;
import flash.util.getTimer;
public class Plasma extends Sprite
{
private const screen: BitmapData = new BitmapData( 0×80, 0×80, false, 0 );
private const dim: Rectangle = new Rectangle( 0, 0, 0×80, 0×80 );
private const palette: Array = new Array();
private const buffer: ByteArray = new ByteArray();
private var plasma: Array;
public function Plasma()
{
//– the screen
stage.scaleMode = ‘noScale’;
stage.quality = ‘low’;
addChild( new Bitmap( screen ) );
//– init fpscounter
initFPSCounter();
//– init Plasma
initPlasma();
addEventListener( ‘enterFrame’ , onEnterFrame );
}
private function onEnterFrame( event: Event ): Void
{
var ps: int = int(getTimer() / 10);
var plsm: Array = plasma;
var pal: Array = palette;
var s: BitmapData = screen;
var buf: ByteArray = buffer;
var pos: int;
var x: int = 0×80;
var y: int = 0×80;
buf.position = 0;
while ( x > 0 )
{
x–;
while ( y > 0 )
{
y–;
buf.writeUnsignedInt( pal[ ((plsm[ x ][ y ] + ps) % 0×100) ] );
//s.setPixel( x, y, pal[ ((plsm[ x ][ y ] + ps) % 0×100) ] );
}
y = 0×80;
}
buf.position = 0;
s.setPixels( dim, buf );
}
}
}[/as]
This was very useful information, as I’m trying to code a game in a similar vein to the DOS games of old, using a global 256-colour palette. There doesn’t seem to be enough info on the net regarding palettes and byte arrays and whatnot, so thanks!