Nào chúng ta lại tiếp tục phần 3 nhé, trong phần này chúng ta sẽ tạo ra đạn để bắn vào vật thể.

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;
Bên trong Constructor chúng ta new bulletlist
Mã:
       bulletList = new LinkedList<Bullet>();
Chúng ta trở lại lớp Ship và them vào method (shoot() ) như sau:
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)
//Và thêm method touch như sau:
Mã:
 
       @Override
       public boolean onSceneTouchEvent(Scene pScene, TouchEvent pSceneTouchEvent) {
              synchronized (this) {
                     ship.shoot();
              }
              return true;
 
       }
Mỗi lần ta touch on the screen thì nó sẽ gọi shoot(), ta thực hiện hàm này ngay ở đây và không cần chuyển nó đến nới khác để xử lý.

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();
OK! Đến đây bạn có thể chạy thử nhé:


Post a Comment Blogger

 
Top