A Flash Developer Resource Site

Results 1 to 20 of 27

Thread: Trying to design some object pooling

Hybrid View

  1. #1
    Senior Member
    Join Date
    May 2006
    Location
    Manhattan
    Posts
    246
    you won't be able to "apply" a type to an already created instance of a different (or ancestor) type.

    In terms of pooling implementation, you can quite simply create a desired number of every type you'll be using in your application. You could map Class to a pool of that type in a Dictionary object to constrain your pool access to a single method. Offer another method to return an object you're done with to the pool. The pooling management class can identify the Class dynamically and return it to the appropriate pool.

  2. #2
    Knows where you live
    Join Date
    Oct 2004
    Posts
    944
    The chances are that its unlikely that object pooling is really the best solution.

    Except in extreme cases, object creation and collection is not going to be a massive performance bottleneck. Object pooling is moderately complex for what you get, and has the risk of the overhead being greater than simply creating objects on demand. Not only that, but the many potential types of objects that need to be pooled sticks a lot of excess complexity in there.

    I assume that your goal is performance in using large quantities of objects.
    There are alternatives to object pooling that may be more appropriate such as the flyweight pattern (http://en.wikipedia.org/wiki/Flyweight_pattern).

    It is far faster to manage creation and deletion of coordinates (Numbers/ints) than complete objects, and opens the possibility for more optimization on top of that (Manually inlining method calls from the flyweight class).

    Pools are far more suited to things like threads where creation may take orders of magnitude more time than the calculations being done. The example provided in the flyweight pattern (Characters being displayed in word processors) is really far more appropriate for bullets, there is many of them, they vary only in coordinates, it is impractical to have each one be an object in itself...
    Last edited by 691175002; 05-20-2008 at 04:58 PM.
    The greatest pleasure in life is doing what people say you cannot do.
    - Walter Bagehot
    The height of cleverness is to be able to conceal it.
    - Francois de La Rochefoucauld

  3. #3
    Senior Member
    Join Date
    Nov 2003
    Location
    Las Vegas
    Posts
    770
    Quote Originally Posted by 691175002
    Except in extreme cases, object creation and collection is not going to be a massive performance bottleneck.
    Try a simple loop test with sufficient iterations, do one test that creates new geom objects (rectangles, points, etc), and do another one that uses object pooling. I think you'll find that object creation with some of Flash's native classes can be a very big bottleneck.

    One special case in the originator's game is the lasers. Generally speaking, a laser will be virtually instantaneous from origin to target. Due to this, you can use a simple pooling method that only has to loop from numberDestroyed to numberCreated, rather than having to rearrange a linked list based on destruction. For bullets and missles this won't work due to some objects being destroyed out of the creation order.

  4. #4
    Script kiddie VENGEANCE MX's Avatar
    Join Date
    Jun 2004
    Location
    England
    Posts
    2,590
    Here's a trimmed-down version of one of my Invasion tests, then. Put this script on your main frame (told you it's sloppy):

    PHP Code:
    stage.scaleMode "noScale";
    stage.quality "LOW";

    var 
    infSheetBMP:infSheet = new infSheet();
    var 
    troops:Sprite = new Sprite();
    var 
    troopPool:Array = new Array();

    var 
    frameRate:int=31;
    var 
    lowest:int=frameRate;
    var 
    checkCounter:int checkRate 8;
    var 
    startTime getTimer();
    var 
    lowestResetCnt=frameRate*5;
    var 
    fps:int 31;

    var 
    tI:int 0;
    var 
    t;

    var 
    te:TextField = new TextField();
    te.text "FPS: 31\nTroops: 0";
    te.autoSize TextFieldAutoSize.LEFT;
    addChild(te);

    function 
    createTroop(tr:Number):void {
        if (
    troopPool.length>0) {
            
    myTroop troops.addChild(troopPool[0]);
            
    troopPool.splice(01);
        } else {
            var 
    myTroop:Infantry = new Infantry(this);
            var 
    infSprite:Bitmap = new Bitmap(infSheetBMP);
            
    myTroop.addChild(infSprite);
            
    troops.addChild(myTroop);
        }
        
    myTroop.init();
    }

    stage.addEventListener(Event.ENTER_FRAMEEnterFrame);
    function 
    EnterFrame(event:Event):void {
        
    createTroop();
        
        
    tI troops.numChildren;
        while (
    tI--) {
            
    troops.getChildAt(tI);
            
    t.eF();
        }
        if(--
    checkCounter==0) {
            
    fr checkRate/((getTimer() - startTime)/1000);
            
    fps int(fr*10)/10;
            if (
    fps<=lowest){
                
    powest=fps;
            } else {
                if(
    fps>frameRate){
                    
    fps=frameRate;
                }
            }
            
    startTime getTimer();
            
    checkCounter checkRate;
        }
        if (--
    lowestResetCnt==0){
            
    lowestResetCnt=frameRate;
            
    lowest=frameRate;
        }
        
    te.text "FPS: "+String(fps)+"\nMCs: "+String(troops.numChildren);

    You'll need to download and put this into your Library:



    And Export it for ActionScript with a Linkage Identifier of infSheet.

    Finally, you'll need an Infantry.as in your project folder saying this:

    PHP Code:
    package {
        
    import flash.display.Sprite;
        
    import flash.display.Bitmap;
        
    import flash.display.BitmapData;
        
    import flash.geom.Rectangle;

        public class 
    Infantry extends Sprite {
            public var 
    _root;
            public var 
    speed:int;
            public var 
    frame:int;
            public var 
    objMode:String;
            public var 
    cond:Boolean;
            public var 
    inc:int;
            
            public var 
    obj:String "Inf";
            
            public var 
    WIDTH:int 35;
            public var 
    HEIGHT:int 54;
            public var 
    FRAMES:int 17;
            
            public var 
    rect:Rectangle;
            
            public function 
    Infantry(mr:Object) {
                
    _root mr;
                
    cacheAsBitmap true;
                
    scrollRect = new Rectangle(0,0WIDTHHEIGHT);
                
    draw();
            }
            public function 
    draw():void {
                
    rect scrollRect;
                
    rect.frame WIDTH;
                
    scrollRect rect;
            }
            public function 
    init():void {
                
    Math.floor(245-Math.random()*12)
                
    = -50-Math.random()*20;
                
    frame 0;
                
    speed 3;
                
    objMode  "Walk";
                
    cond true;
                
    inc Math.round(Math.random()*5);
                
    WIDTH 35;
                
    HEIGHT 54;
                
    FRAMES 17;
                
    scrollRect = new Rectangle(0,0WIDTHHEIGHT);
            }
            public function 
    eF():void {
                if (
    <= 300) {
                    
    x-=-speed;
                } else if (
    x>300) {
                    
    -= 21 ;
                    
    -= -10;
                    
    objMode "Die";
                    
    frame 0;
                    
    FRAMES 19;
                    
    WIDTH 54;
                    
    HEIGHT 44;
                    
    scrollRect = new Rectangle(0121WIDTHHEIGHT);
                }
                
    draw();
                
    frame++;
                if (
    objMode=="Die") {
                    if (
    frame==FRAMES) {
                        
    _root.troops.removeChildAt(_root.tI);
                        
    _root.troopPool.push(this);
                    }
                } else {
                    if (
    frame==FRAMES) {
                        
    frame 0;
                    }
                }
            }
        }

    Sorry if it doesn't work; I haven't tested that, so I might've removed some unnecessary stuff. I'd compile it all for you, but Flash 9 doesn't run on my Intel Mac. As for webgeek's version... you'd need to ask him for that.

    Oh, bear in mind that while object pooling does get rid of the bottleneck of object instantiation, you can still create a far faster entity engine using copyPixels(). My non-pooling copyPixels() engine runs about 20 times faster than this. Comparison:

    Pooling sprites (FPS capped at 31, so note that this isn't a very fair benchmark):
    http://www.birchlabs.co.uk/Invasion5F9.swf
    copyPixels():
    http://www.birchlabs.co.uk/Invasion_5.html
    Last edited by VENGEANCE MX; 05-21-2008 at 12:20 PM.
    http://www.birchlabs.co.uk/
    You know you want to.

  5. #5
    Hype over content... Squize's Avatar
    Join Date
    Apr 2001
    Location
    Lost forever in a happy crowd...
    Posts
    5,926
    V, pooling isn't limited to sprites mate.

    I'm sure we've spoken about this before, you can still use bobs with pooling rather than just sprites.

    Squize.

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