A Flash Developer Resource Site

Page 2 of 3 FirstFirst 123 LastLast
Results 21 to 40 of 51

Thread: AS3 is FAST! Redux - CopyPixels vs. Sprite Pooling

  1. #21
    Senior Member webgeek's Avatar
    Join Date
    Sep 2000
    Posts
    1,356
    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.

  2. #22
    Script kiddie VENGEANCE MX's Avatar
    Join Date
    Jun 2004
    Location
    England
    Posts
    2,590
    Hadn't considered that at the time. =]

    Also, I like that sprite sheet. It's fun to scroll across it horizontally with my Mighty Mouse.
    http://www.birchlabs.co.uk/
    You know you want to.

  3. #23
    Script kiddie VENGEANCE MX's Avatar
    Join Date
    Jun 2004
    Location
    England
    Posts
    2,590
    Okay, started Invasion 5 again with a copyPixels()-based engine...

    http://www.birchlabs.co.uk/Invasion5CP.swf

    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.

    http://www.birchlabs.co.uk/
    You know you want to.

  4. #24
    hippie hater Cimmerian's Avatar
    Join Date
    Oct 2006
    Location
    over there
    Posts
    599
    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

  5. #25
    Senior Member webgeek's Avatar
    Join Date
    Sep 2000
    Posts
    1,356
    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.

  6. #26
    Junior Member
    Join Date
    Jan 2002
    Posts
    18
    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 =)
    Got Milk?
    FaeKitty >^.^<

  7. #27
    Please, Call Me Bob trogdor458's Avatar
    Join Date
    Aug 2006
    Location
    Pensacola, FL
    Posts
    915
    eh? i've only used copyPixels once:

    http://trogdorffe.tripod.com/tilesystem.htm

    (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

  8. #28
    Hype over content... Squize's Avatar
    Join Date
    Apr 2001
    Location
    Lost forever in a happy crowd...
    Posts
    5,926
    I think FaeKitty was asking if someone who'd done some of these as3 tests wouldn't mind posting the source.

    Squize.

  9. #29
    Script kiddie VENGEANCE MX's Avatar
    Join Date
    Jun 2004
    Location
    England
    Posts
    2,590
    Bleh... you're gonna get to see my coding practices now, aren't you?

    http://www.birchlabs.co.uk/CopyPixelsSource.zip

    (there are no comments, have fun...)

    Sprite sheet's here:



    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.
    http://www.birchlabs.co.uk/
    You know you want to.

  10. #30
    Junior Member
    Join Date
    Jan 2002
    Posts
    18
    Okie dokie. I'll see if I can understand how it all works. Thank you =)
    Got Milk?
    FaeKitty >^.^<

  11. #31
    Junior Member
    Join Date
    Jan 2002
    Posts
    18
    Hmmm, I get the following error when I try to run/test it in Flash CS3 Pro:

    >>
    ArgumentError: Error #1063: Argument count mismatch on ArrowSheet$iinit(). Expected 2, got 0.
    at CopyPixelsSource_fla::MainTimeline/CopyPixelsSource_fla::frame2()

    >>

    Anyone know what the problem might be? =/
    Got Milk?
    FaeKitty >^.^<

  12. #32
    Senior Member webgeek's Avatar
    Join Date
    Sep 2000
    Posts
    1,356
    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.

  13. #33
    Junior Member
    Join Date
    Jan 2002
    Posts
    18
    Thank you webgeek. I changed the forth line from:

    var arrowSpriteSheet:ArrowSheet = new ArrowSheet();

    to:

    var arrowSpriteSheet:ArrowSheet = new ArrowSheet(0,0);

    Still not sure why it needed arguments, but it works for me now.

    I've looked through it and I believe I understand how the technique works now. Thank you very much, VENGEANCE MX =)
    Last edited by FaeKitty; 06-02-2007 at 08:58 PM.
    Got Milk?
    FaeKitty >^.^<

  14. #34
    Developer
    Join Date
    Apr 2007
    Location
    UK
    Posts
    324
    You legend vengeance!

  15. #35
    Senior Member
    Join Date
    Dec 2005
    Location
    No where
    Posts
    105
    **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.

    Basic class and the whole thing is at the end:
    code:

    package core.rendering
    {
    import core.Vector;
    import flash.filters.DropShadowFilter;
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.MovieClip;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.geom.ColorTransform;
    import flash.geom.Matrix;
    import flash.geom.Rectangle;
    import flash.geom.Point;
    import flash.filters.BlurFilter;
    import flash.filters.ConvolutionFilter;
    public class Renderer extends Sprite
    {
    private var objects:Array;

    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);


    obd.draw(objects[i], m);
    }
    }
    holder[i] = obd;
    }catch (e:Error){
    }
    //objects = holder;
    }
    objects = holder;
    }

    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);
    }

    public function spark(xy:Vector, name:String):void{
    try{
    counter = blurInterval;
    temp = objects[name];
    //from render()
    tempVec = getObDimensions(temp);
    tempPoint.x = xy.x-tempVec.x/spacing/2;
    tempPoint.y = xy.y-tempVec.y/spacing/2;

    rect = new Rectangle(0,0,tempVec.x/spacing, tempVec.y/spacing);

    dispBtmpD.copyPixels(temp,rect,tempPoint,null,null ,true);
    } catch (e:Error){
    }
    }

    public function render(r:RenderOptions):void{
    temp = objects[r.item];

    rect.width = temp.width/obDim.x;
    rect.height = temp.height/obDim.y;

    tempPoint.x = r.pos.x-rect.width/spacing/2;
    tempPoint.y = r.pos.y-rect.height/spacing/2;

    rot = ((r.rotation-360*((r.rotation/360) << 0))/rotInterval) << 0;

    row = (rot/obDim.x) << 0;

    rect.y = row*rect.height;

    rect.x = rect.width*(rot-(row*obDim.x));
    rect.width /= spacing;
    rect.height /= spacing;

    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;

    if(counter%blurInterval==0){
    blurBtmpD.copyPixels(dispBtmpD,dispBtmpD.rect,new Point(),null,null,true);
    }
    blurBtmpD.colorTransform(new Rectangle(0,0, dim.x, dim.y), new ColorTransform(1,1,1,blurDecay));
    }

    public function checkHit(v:Vector):Boolean{
    return dispBtmpD.hitTest(new Point(0,0),0x55,new Point(v.x, v.y));
    }
    }
    }



    ok hope this helps
    Attached Files Attached Files

  16. #36
    Developer
    Join Date
    Apr 2007
    Location
    UK
    Posts
    324
    For some reason the provided SWF refuses to work for me

  17. #37
    Senior Member
    Join Date
    Dec 2005
    Location
    No where
    Posts
    105
    the swf under the folder bin called "NewShooter" should work

  18. #38
    Member
    Join Date
    Jun 2007
    Posts
    64
    Quote Originally Posted by VENGEANCE MX
    Bleh... you're gonna get to see my coding practices now, aren't you?

    http://www.birchlabs.co.uk/CopyPixelsSource.zip

    (there are no comments, have fun...)

    Sprite sheet's here:



    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.

    Thanks

  19. #39
    Script kiddie VENGEANCE MX's Avatar
    Join Date
    Jun 2004
    Location
    England
    Posts
    2,590
    You'd loop through all the objects in the arrows array, and compare their coordinates (plus their width and height) with the mouse's coordinates.
    http://www.birchlabs.co.uk/
    You know you want to.

  20. #40
    Funkalicious TOdorus's Avatar
    Join Date
    Nov 2006
    Location
    Nijmegen, Netherlands
    Posts
    697
    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

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  




Click Here to Expand Forum to Full Width

HTML5 Development Center