第39節 - LibGDX: Tiled (Bullet Class)
這一節我會介紹LibGDX遊戲的Bullet Class,我在第38節 - LibGDX: Tiled (Collision Detection)介紹過如何利用Tiled Map Editor造出碰撞效果,這一節會加入發射子彈的方法。
注意,發射子彈的程式有不同的方法,因為子彈也是類別的物件(instance),如果不斷發射子彈,就須要產生很多物件,浪費資源,有些人會選擇利用Object Pool方法產生子彈,我會在其他章節詳細介紹Object Pool的用法,現在我會介紹一個十分簡單的方法。
執行結果:
以下是LibGDX: Tiled (Bullet Class)程式執行的結果:
製作子彈(Bullet)圖片

- 我們可以製作一張向右的子彈圖片(bulletRight.png),再傳入Texture物件(bulletRight)和製作一張向左的子彈圖片(bulletLeft.png),再傳入Texture物件(bulletLeft)。
不過另一個方法是利用TextureRegion類別的flip()方法,把圖片反轉,這樣做可以減少記憶體資源,所以bulletLeft須要是TextureRegion類別的物件。
發射子彈的程式
1) Bullet.java程式
我們可以把以下Bullet.java的程式碼寫在MyDemo39.java內,不過這次我會建立一個獨立的Bullet.java類別,如下圖:

- 首先在Bullet類別的Constructor內,把bulletPosition和bulletVelocityX傳入。
bulletPosition就是主角hero1的子彈發射位置。 - 建立一個update()方法,把子彈的位置加上bulletVelocityX傳入的數值。
2) MyDemo39.java新加入部分
以下部分會列出在MyDemo39.java程式新加的部分,如下圖:

- 建立一個ArrayList物件(bulletManager),它屬於bullet類,bulletManager主要用來儲存和去除bullet Array。
- 利用TextureRegion類別的flip()方法,把bullet圖片反轉,這樣做可以減少記憶體資源,所以bulletLeft須要是TextureRegion類別的物件。
- 當我們按下"F"鍵,如果主角hero1面向右,把+bulletVelocityX傳入,如果主角hero1面向左,把-bulletVelocityX傳入。
- 用while Loop執行bulletCounter由0至按下"F"鍵的數目,按下"F"鍵的數目 = bulletManager.size()。
- 把bullet用bulletManager.get()方法傳入currentBullet內。
- 執行currentBullet.update()方法,移動每一粒子彈。
- 偵測bullet是否在屏幕右面多100px和屏幕左面多100px內。
- 如果bullet是否在屏幕右面多100px和屏幕左面多100px內,顯示bullet在屏幕上。
- 否則,如果子彈飛出了屏幕右面多100px,就會用bulletManager.remove()方法去除bullet Array,同樣,如果子彈飛出了屏幕左面多100px,就會用bulletManager.remove()方法去除bullet Array。
- 當while Loop執行了一次後,把bulletCounter加上一,再執行一次,直至bulletCounter<bulletManager.size()。
3) ArrayList BulletManager
建立一個ArrayList物件(bulletManager),它屬於bullet類,bulletManager主要用來儲存和去除bullet Array,如下圖:

- 建立一個ArrayList物件(bulletManager),它屬於bullet類。
- 每按一次"F"鍵,bulletManager.add()方法把bullet儲存。
- 因為bulletManager是屬於ArrayList物件,我們可以用bulletManager.size()來取得ArrayList的大小。
- 我們也可以用bulletManager.get()來取得指定的bullet。
4) Remove Bullet
因為bulletManager是屬於ArrayList物件,我們可以用bulletManager.remove()方法來去除指定的bullet,如下圖:

- 把bulletCounter數值傳入bulletManager.remove()方法內。
- 第1粒bullet用bulletCounter=0代表。
- 如果子彈飛出了屏幕右面多100px,就會用bulletManager.remove()方法去除bullet Array,同樣,如果子彈飛出了屏幕左面多100px,就會用bulletManager.remove()方法去除bullet ArrayList的一格element。
- 注意,當ArrayList去除了一格element,ArrayList的element就會順延一格。
LibGDX程式
例子1 - 2D Platformer Game with Bullet Class
這個例子會用LibGDX示範Bullet Class:
DesktopLauncher.java

- DesktopLauncher是PC Desktop的Starter Class,我們在DesktopLauncher內設定顯示的大小為1024 X 768 px。

- 把甩bullet.png、hero1Atlas.pack和hero1Atlas.png儲存到Android的Assets文件夾內(/data/...)。
把map.tmx和tileAtlas.png儲存到Android的Assets文件夾內(/map/...)。
Bullet.java

- 首先在Bullet類別的Constructor內,把bulletPosition和bulletVelocityX傳入。
bulletPosition就是主角hero1的子彈發射位置。 - 建立一個update()方法,把子彈的位置加上bulletVelocityX傳入的數值。
MyDemo39.java

- 建立bulletRight、 bulletLeft、bullet、currentBullet和bulletManager變數(Variable)。
- 製作一張向右的子彈圖片(bullet.png),再傳入Texture物件(bulletRight)和利用TextureRegion類別的flip()方法,把圖片反轉,這樣做可以減少記憶體資源,所以bulletLeft須要是TextureRegion類別的物件。
- 用while Loop執行bulletCounter由0至按下"F"鍵的數目,按下"F"鍵的數目 = bulletManager.size()。
- 把bullet用bulletManager.get()方法傳入currentBullet內。
- 最後呼叫dispose()方法,執行batch.dispose();、hero1Atlas.dispose();、tiledMap.dispose(); 和bulletRight.dispose(); 釋放資源。
- 當我們按下"F"鍵,如果主角hero1面向右,把+bulletVelocityX傳入,如果主角hero1面向左,把-bulletVelocityX傳入。
執行currentBullet.update()方法,移動每一粒子彈。
偵測bullet是否在屏幕右面多100px和屏幕左面多100px內。
如果bullet是否在屏幕右面多100px和屏幕左面多100px內,顯示bullet在屏幕上。
否則,如果子彈飛出了屏幕右面多100px,就會用bulletManager.remove()方法去除bullet Array,同樣,如果子彈飛出了屏幕左面多100px,就會用bulletManager.remove()方法去除bullet Array。
當while Loop執行了一次後,把bulletCounter加上一,再執行一次,直至bulletCounter<bulletManager.size()。
執行程式:
