OK! Trước khi vào phần này bạn bạn nên tham khảo Object pool của bài viết TKminh ở vietandroid.com nhé, ở đây tôi không giới thiệu nó.
Let’s start:
Để bắn đi từ Ship tới mục tiêu, chúng ta cần những viên đạn, vì vậy chúng ta sẽ tạo ra đạn ở đây: Ta tạo ra lớp đạn và đặt tên là Bullet
Mã:
public class Bullet { public Rectangle sprite;//Đạn hình vuông nhỏ public Bullet(){ sprite = new Rectangle(0,0,10,10,AndEngineTutorial2Activity.getSharedInstance(). getVertexBufferObjectManager()); sprite.setColor(1f,0f,0f); } }
Mỗi viên đạn là 1 hình vuông có size 10x10 pixels, và màu nó là màu đỏ (RGB). Ở đây bạn cũng có thể sử dụng hình ảnh thay vì các viên đạn bạn chỉ cần thay sprite thành Sprite và điều chỉnh một chút bên trong lớp là OK.
OK Bây giờ chúng ta sẽ sử dụng pool để tái sử dụng lại các viên đạn
Chúng ta tạo ra 1 lớp mới đặt tên là: BulletPool
Mã:
public class BulletPool extends GenericPool<Bullet> { public static BulletPool instance; public static BulletPool sharedBulletPool() { if (instance == null) instance = new BulletPool(); return instance; } private BulletPool() { super(); } @Override protected Bullet onAllocatePoolItem() { // TODO Auto-generated method stub return new Bullet(); } // Dung de Recycle 1 bullet protected void onHandleRecycleItem(final Bullet b) { b.sprite.clearEntityModifiers(); b.sprite.clearUpdateHandlers(); b.sprite.setVisible(false); b.sprite.detachSelf(); } }
Đầu tiên chúng ta cần phải theo dõi xem viên đạn bắn ra từ đâu, và đi như thế nào từ đâu đến đâu để chúng ta còn loại bỏ nó. Và khi viên đạn gặp cái gì đó (đích, hoặc ngoài màn hình).
Bây giờ chúng ta hãy trở lại lớp GameScene tạo mới LinkedList của các viên đạn và biến để đếm chúng.
Mã:
public int bulletCount; public LinkedList<Bullet> bulletList;
Mã:
bulletList = new LinkedList<Bullet>();
Mã:
public void shoot() { if (!moveable) return; GameScene scene = (GameScene) AndEngineTutorial2Activity.getSharedInstance().mCurrentScene; Bullet b = BulletPool.sharedBulletPool().obtainPoolItem(); b.sprite.setPosition(sprite.getX() + sprite.getWidth() / 2, sprite.getY()); MoveYModifier mod = new MoveYModifier(1.5f, b.sprite.getY(), -b.sprite.getHeight()); b.sprite.setVisible(true); b.sprite.detachSelf(); scene.attachChild(b.sprite); scene.bulletList.add(b); b.sprite.registerEntityModifier(mod); scene.bulletCount++; }
Kiểm tra nếu Ship mà không dịch chuyển được thì bỏ qua (Vì không dịch chuyển được thì không bán đạn làm gì)
Chúng ta có được Scene hiện tại. và lấy được 1 viên đạn từ pool sau đó chúng ta thiết lập nó ở vị trí giữa bên trên Ship.
Chúng ta tạo ra 1 MoveYModifier và dịch chuyển viên đạn này dọc theo trục Y.
Trong trường hợp hiện tại của chúng ta, chúng ta cho di chuyển viên đạn từ vị trí ban đầu tới vị trí hết màn hình. Và ta cho hiển thị viên đạn này lên, và sau đó detach bản thân nó từ pool (Mặc dù khi ta lấy nó ra bằng obtain….() thì bản thân nó đã detach rồi, nhưng ở đây tôi cứ viết thêm cho nó rõ hơn).
Tiếp theo chúng ta attach viên đạn tới Scene hiện tại và đồng thời add nó tới linked list, sau đó đăng ký modifier nếu chúng ta không thực hiện điều này thì viên đạn không thể dịch chuyển được, Sau đó ta tăng biến đếm lên 1 đơn vị.
Trước khi chúng ta chạy chương trình này chúng ta cần thực hiện thêm một số bước nhỏ.
Ta trở lại GameScene và implements IOnSceneTouchListener
Trong constructor chúng ta
Mã:
setOnSceneTouchListener(this)
Mã:
@Override public boolean onSceneTouchEvent(Scene pScene, TouchEvent pSceneTouchEvent) { synchronized (this) { ship.shoot(); } return true; }
OK đến đây khi bạn touch thì đã có bullet rồi. Nhưng chúng ta còn một công việc nữa đó là chúng ta chưa làm sạch các viên đạn (Không trả lại chúng tới pool) khi chúng tới đích vì vậy chúng ta sẽ làm tiếp việc này trước khi chúng ta kết thúc phần này.
Ta thêm vào trong GameScene method sau:
Mã:
public void cleaner() { synchronized (this) { Iterator<Bullet> it = bulletList.iterator(); while (it.hasNext()) { Bullet b = it.next(); if (b.sprite.getY() <= -b.sprite.getHeight()) { BulletPool.sharedBulletPool().recyclePoolItem(b); it.remove(); continue; } } } }
Chúng ta lặp đi lặp lại trên linked list (Sử dụng 1 bộ lặp) và nếu viên đạn đi ra màn hình, chúng ta sẽ trả lại nó về pool (Tái sử dụng nó), và sau đó remove nó từ linked list và tiếp tục lặp lại.
Bây giờ chúng ta chỉ cần gọi method này, chúng ta sẽ thực hiện điều này qua GameLoopUpdateHanler bằng cách add thêm dòng lệnh sau vào onUpdate()
Mã:
((GameScene)AndEngineTutorial2Activity.getSharedInstance().mCurrentScene).cleaner();
Post a Comment Blogger Facebook
Post a Comment