Cách sử dụng object pool - Game with Andengine

Thảo luận trong 'Điện thoại, viễn thông' bắt đầu bởi khaipt, 2/9/12.

  1. khaipt New Member

    khaipt

    Tham gia ngày:
    30/6/12
    Bài viết:
    22
    Đã được thích:
    34
    Điểm thành tích:
    0
    Mình vừa nghiên cứu xong phần Object Pool của AndEngine, xin chia sẽ cùng các bạn.
    Trong game, đặc biệt là trên mobile, việc tạo quá nhìu instance cho cùng 1 object sẽ gây chiếm dụng bộ nhớ, làm cho game chạy chậm đi hoặc giựt giựt. Ví dụ game bắn súng, khi người dùng bắn 1 viên đạn ra , bạn tạo 1 object viên đạn, người dùng bắn 100 viên, bạn tạo 100 object, sẽ rất tốn bộ nhớ ... Sẽ tốt hơn khi có thể sử dụng lại nếu có 1 object viên đạn nào đó mà nó finish xong chu trình của nó. Do đó object pool ra đời. http://337play.net/images/ym_smilies/16.gif

    Và đây là ví dụ của mình, cứ mỗi giây sẽ tạo 1 object FaceSprite, di chuyển dọc trên màn hình và khi ra khỏi màn hình (tức là ko còn hiển thị trên màn hình nữa) thì sẽ đc lưu vào object pool và sẽ đc sử dụng lại.
    PHP:
    package com.myapp.test;

    import org.anddev.andengine.entity.IEntity;
    import org.anddev.andengine.entity.modifier.LoopEntityModifier;
    import org.anddev.andengine.entity.modifier.PathModifier;
    import org.anddev.andengine.entity.modifier.PathModifier.IPathModifierListener;
    import org.anddev.andengine.entity.modifier.PathModifier.Path;
    import org.anddev.andengine.entity.sprite.AnimatedSprite;
    import org.anddev.andengine.opengl.texture.region.TiledTextureRegion;
    import org.anddev.andengine.util.MathUtils;
    import org.anddev.andengine.util.constants.TimeConstants;

    public class 
    FaceSprite extends AnimatedSprite implements TimeConstants {

        private 
    Path path;
        private 
    LoopEntityModifier lem ;
        private 
    boolean isAttachToScene;
        
        public 
    FaceSprite(float pXfloat pYfloat pTileWidthfloat pTileHeight,
                
    TiledTextureRegion pTiledTextureRegion) {
            
    super(pXpYpTileWidthpTileHeightpTiledTextureRegion);
            
            
    isAttachToScene false;
            
    settingMovePath();
        }

        private 
    FaceSprite getInstance() {
            return 
    this;
        }
        
        public 
    boolean isAttachToScene() {
            return 
    isAttachToScene;
        }

        public 
    void setAttachToScene(boolean isAttachToScene) {
            
    this.isAttachToScene isAttachToScene;
        }
        
        private 
    void settingMovePath() {
            
    int x1 MathUtils.random(13) * 100 70;
            
    int y1 500;
            
    int x2 x1;
            
    int y2 50;
            
    path = new Path(3).to(x1,y1).to(x2y2).to(x1y1);
            
            
    PathModifier pm = new PathModifier(33pathnull, new IPathModifierListener() {

                @
    Override
                
    public void onPathStarted(PathModifier pPathModifier,
                        
    IEntity pEntity) {
                    
                }

                @
    Override
                
    public void onPathWaypointStarted(PathModifier pPathModifier,
                        
    IEntity pEntityint pWaypointIndex) {
                    
                    
    // method animate truyen vao frame duration: thoi gian cua moi frame hien thi
                    // frame bat dau va frame ket thuc fai tuong ung voi so frame
                    
    int startFrame 1;
                    
    int endFrame 5;
                    
    int frameDuration 200;
                    
    getInstance().animate(new long[]{frameDurationframeDurationframeDurationframeDurationframeDuration}, startFrameendFrametrue);
                    
                }

                @
    Override
                
    public void onPathWaypointFinished(PathModifier pPathModifier,
                        
    IEntity pEntityint pWaypointIndex) {
                    
    // TODO Auto-generated method stub
                    
                
    }

                @
    Override
                
    public void onPathFinished(PathModifier pPathModifier,
                        
    IEntity pEntity) {
                    
    // TODO Auto-generated method stub
            
                
    }}
                );
            
    lem = new LoopEntityModifier(pm);
            
    this.registerEntityModifier(lem);
        }
    }
    Đây là lớp FacePool, lớp này sẽ extend GenericPool<object>
    - ArrayList<FaceSprite> arrFaceSprite : chứa tất cả object FaceSprite đc tạo ra
    - Method onAllocatePoolItem dùng để tạo object FaceSprite và gắn nó và Scene bên trong class này luôn. Vì nếu bạn gọi và add từ bên ngoài thì khi recycle lại object này, nó sẽ di chuyển càng lúc càng nhanh (theo mình nghiên cứu là do nó register lại updatehandler của object FaceSprite này)
    - Method onHandleRecycleItem: dùng recycle 1 object cụ thể
    - Method onHandleObtainItem: reset lại object như lúc ban đầu
    - Method checkAndRecycle: mình sẽ lặp qua hết các object trong Pool và sẽ recycle lại nếu thỏa điều kiện
    PHP:
    package com.myapp.test;

    import java.util.ArrayList;

    import org.anddev.andengine.engine.Engine;
    import org.anddev.andengine.opengl.texture.region.TiledTextureRegion;
    import org.anddev.andengine.util.pool.GenericPool;

    public class 
    FacePool extends GenericPool<FaceSprite> {
        
        private 
    TiledTextureRegion ttr;
        private 
    Engine mEngine;
        private 
    ArrayList<FaceSpritearrFaceSprite;
        
        public 
    FacePool(Engine engineTiledTextureRegion pttr) {
            
    mEngine engine;
            
    ttr pttr;
            
    arrFaceSprite = new ArrayList<FaceSprite>();
        }
        
        @
    Override
        
    public FaceSprite onAllocatePoolItem() {
            
    FaceSprite fs=  new FaceSprite(004545ttr.clone());
            
    fs.setAttachToScene(true);
            
    mEngine.getScene().attachChild(fs);
            
    arrFaceSprite.add(fs);
            return 
    fs;
        }
        
        @
    Override
        
    public void onHandleRecycleItem(final FaceSprite fs){
            if (
    fs.isAttachToScene()) {
                
    fs.setIgnoreUpdate(false);
                
    fs.setVisible(true);
                
    fs.setAttachToScene(false);
            }
            
        }
        
        @
    Override
        
    public void onHandleObtainItem(final FaceSprite fs) {
            
    fs.reset();
        }
        
        public 
    void checkAndRecycle() {
            for (
    FaceSprite fs arrFaceSprite) {
                if (
    fs.getY()>150) {
                    
    this.recyclePoolItem(fs);
                }
            }
        }
    }
        
    Và đây là đoạn code khi sử dụng object pool, mình sử dụng TimerHandler với method onTimePassed để liên tục tạo object FaceSprite sau mỗi giây
    PHP:
            
            FACEPOOL 
    = new FacePool(engine,ttr);

            
    TimerHandler th = new TimerHandler(1true, new ITimerCallback() {
                @
    Override
                
    public void onTimePassed(TimerHandler pTimerHandler) {
                    
    FACEPOOL.obtainPoolItem();
                    
                    
    FACEPOOL.checkAndRecycle();
                }
            });
            
    engine.registerUpdateHandler(th);
        }
      
    Xong, hi vọng giúp ích các bạn trong việc nghiên cứu về Object Pool của AndEngine
    DOWNLOAD LINK
    tkminh nguồn:cunghocandroid
     
    Đang tải...
  2. truongnv92 New Member

    truongnv92

    Tham gia ngày:
    13/5/13
    Bài viết:
    1
    Đã được thích:
    0
    Điểm thành tích:
    0
    Giới tính:
    Nam
    a ơi ,a có thể comment code ko , nhiều đoạn khó hiểu quá, cái PathModifier và LoopEntytiModifier có nhiệm vụ làm gì a
     
  3. vangioicnt Moderator

    vangioicnt

    Tham gia ngày:
    11/10/12
    Bài viết:
    180
    Đã được thích:
    352
    Điểm thành tích:
    0
    PathModifier : Tạo ra 1 đường để cho FaceSprite di chuyển theo đường đó.

    LoopEntytiModifier : Tứ là sẽ lặp đi lặp lại 1 Modifier nào đó. Cụ thể ở đây là lặp đi lặp lại cái PathModifier .
     

Chia sẻ trang này