I'd suggest that if you were to use this technique in a real game you would simply create the sprite sheet on the fly rather then manually. It doesn't take much code to start with a single image and rotate it 360 degrees in 5 degree increments and save all that into a bitmap.
That's moving 7,000+ sprites at 18 fps for me (and that's in the browser). Using a significantly smaller sprite sheet than the last copyPixels() example, so it's not having to push as many pixels, I think.
Now, there is still other thing to test, it is if creating another Bitmap each frame is faster tham erasing the first one,and also there are many ways to erase the first one,copyPixels, fillRect, or make him = new BitmapData()...
But you know what,if the diference is one or two frames, i wonder if in AS3 that worth, is AS2 every drop counts but in AS3 you already have so much speed that, compared to what you already have,that little improvement dont add much
But you know what,if the diference is one or two frames, i wonder if in AS3 that worth, is AS2 every drop counts but in AS3 you already have so much speed that, compared to what you already have,that little improvement dont add much
If it's consistently faster then it's worth it. Simple as that Saving CPU and increasing framerate is cumulative. The more we save, the more we have to other things and the less we have to tune when the game is finished.
Are any of you who have this all worked out willing to share a simple little working example with sourcecode of this efficient method in action for those of us wanting to learn more about how this actually works? I mean, I get the basic idea of how the technique is supposed to work, but nothing beats having a simple working example to dig through and examine. If so, that’s be swell =)
(arrow keys to move)
frankly it doesn't seem terribly fast
it also has a very minor bug which I can't pinpoint, when going left, all the tiles are one pixel off
The transparent arrows are there because the arrows fade out, and it's faster to copy the pixels of a pre-rendered transparent arrow than apply a ColorTransform to it every time it's needed.
The problem is that Vengence is using AS3 in Flash 8, not CS3. There are some subtle API changes between the two. You will have to double check those methods against the documented API to see whats wrong.
**warning** this was made in flex, it might take a little messing around with to fit it into flash CS3
ok, here I have a class thats a little different from Vengeance's. It runs a little slower, but it has more options like motion tails, lighting up the background, and a few filters. But anyways this one accepts an array of display objects (bunch of swfs) and then it creates a sprite sheet for each (automatically rotates em and draws them on its own sprite sheet).
The way it works is you create an instance of it and just use addChild() to add it to the stage. Then at the begining of each frame call onBeforeRendering() to set things up, then loop through your array of obects and have them make a RenderOptions (another class) and call render(renderOptionsThing). Then at the end call onAfterRendering().
May seem a little complex, but its nice because each object only has to do
new RenderOptions(new Vector(x,y), "smallAsteriod", rotation);
Alright heres the full source (just please dont laugh at my bad coding ). And dont make the exact same game I am as I'm gonna go somewhere with this.
private var dispBtmpD:BitmapData;
private var dispBtmp:Bitmap;
private var blurBtmpD:BitmapData;
private var blurBtmp:Bitmap;
private var counter:int;
private var dim:Vector;
private var blurDecay:Number;
private var blurInterval:int;
public static var instance:Renderer;
private var temp:BitmapData;
private var tempPoint:Point;
private var rect:Rectangle = new Rectangle(0,0,0,0);
private var rot:Number;
private var obDim:Vector = new Vector(9,8);
private var rotInterval:Number = 5;
private var tempVec:Vector;
private var row:Number;
private var spacing:Number = 1.2;
public function Renderer(_dim:Vector, _objects:Array)
{
super();
instance = this;
counter = 1;
dim = _dim;
objects = _objects;
setupObjects();
setupBitmaps();
blurDecay = 0.87;
blurInterval = 2;
tempPoint = new Point(0,0);
}
private function setupObjects():void{
var holder:Array = [];
for(var i:String in objects){
try{
//create a 9 by 8 grid for 5 degree rotations
var obd:BitmapData = new BitmapData(objects[i].width*spacing*obDim.x, objects[i].height*spacing*obDim.y, true, 0x00000000);
var m:Matrix;
for(var j:int = 0; j<obDim.x; j++){
for(var k:int = 0; k<obDim.y; k++){
m = new Matrix();
//offset by one so first box is 0 degrees the 8 is (9-1)
m.translate(-objects[i].width/2, -objects[i].height/2);
m.rotate(Vector.D_TO_R*(rotInterval*(j+(k*obDim.x) )));
m.translate(j*objects[i].width*spacing+objects[i].width/2, k*objects[i].height*spacing+objects[i].height/2);
private function setupBitmaps():void{
dispBtmpD = new BitmapData(dim.x, dim.y, true, 0x00000000);
dispBtmp = new Bitmap(dispBtmpD);
blurBtmpD = new BitmapData(dim.x, dim.y, true, 0x00000000);
blurBtmp = new Bitmap(blurBtmpD);
addChild(blurBtmp);
addChild(dispBtmp);
}
public function addToObjects(item:String, object:*):void{
objects[item] = object;
}
public function setBlurDecay(n:Number):void{
blurDecay = n;
}
public function getBlurDecay():Number{
return blurDecay;
}
public function setBlurInterval(i:int):void{
blurInterval = i;
}
public function getBlurInterval():int{
return blurInterval;
}
public function getDimensions():Vector{
return dim;
}
public function setDimensions(v:Vector):void{
dim = v;
}
public function getDisplayBtmp():Bitmap{
return dispBtmp;
}
public function getBlurBtmp():Bitmap{
return blurBtmp;
}
public function flash():void{
var flashBtmpD:BitmapData = new BitmapData(dim.x, dim.y,true, 0x10FFFFFF);
blurBtmpD.copyPixels(flashBtmpD,flashBtmpD.rect, new Point(0,0),null,null,true);
//blurBtmpD.colorTransform(blurBtmpD.rect, new ColorTransform(1,1,1,1,10,10,10));
}
private function getObDimensions(ob:*):Vector{
return new Vector(ob.width/obDim.x, ob.height/obDim.y);
}
dispBtmpD.copyPixels(temp,rect,tempPoint,null,null ,true);
}
public function onBeforeRendering():void{
counter++;
if(counter>1000){
counter = 1;
}
dispBtmpD = new BitmapData(dim.x, dim.y, true, 0x00000000);
dispBtmpD.lock();
}
public function onAfterRendering():void{
dispBtmpD.applyFilter(dispBtmpD, dispBtmpD.rect, new Point(0,0),new BlurFilter(2,2));
dispBtmpD.unlock();
dispBtmp.bitmapData = dispBtmpD;
The transparent arrows are there because the arrows fade out, and it's faster to copy the pixels of a pre-rendered transparent arrow than apply a ColorTransform to it every time it's needed.
Thanks for posting this demo as I'm still learning the whole copypixel() thing.
My question is somewhat off topic, but possibly still related... Lets say for some reason you wanted to be able to detect if the user clicked on one of the arrows. How would you go about doing that?
I've only ever used the movieclip approach where I can simply add a mouseevent handler.
Hmm... I guess I'll start learning AS3 then, impressive!
The big bitmap also makes it possible to add dynamic lighting and distortions (fire, explosions). Don't know if those are to demanding to calculate realtime, but hey, it's something to do with the proccesing power this method has made avaible