Android基於box2d開發彈弓類遊戲[五]-------------發射子彈

八.發射子彈

我們前期的準備基本上已經完成了。發射臂已經準備就緒了。接下來,開始創建子彈!並且通過發射器發射子彈!

1.     在世界中加入子彈

首先創建一個子彈類Bullet.java類,實現BodyInterface 接口。實現方式與發射器類catapultArm.java類似,此處略。

 首先創建所需的變量:

//用於存放子彈對象的集合
private Set<Body> bullet = new HashSet< Body >();    private final int BulletCount = 4; //子彈數量
private Bitmap bulletBitmap; //子彈圖片

MainView.java主類中,編寫創建子彈CreateBulletBody方法

複製代碼
 /**
     * 創建子彈
     * @param bitmap
     * @param x
     * @param y
     * @param width
     * @param height
     * @param isStatic
     * @return
     */
    public void createBulletBody(int count)
    {
    float pos = 62.0f; //子彈距離場景左端的位置
    if(count >0)
    {
        float delta = 50f; //子彈之間的間隔
       
        for(int i=0;i<count;i++, pos += delta)
        {
           PolygonShape pd = new PolygonShape();
          
           //創建一個多邊形的物體
           Vec2[] vec2s = new Vec2[6];
           vec2s[0] = new Vec2(-0.6f, 0.66f);
           vec2s[1] = new Vec2(-0.8f, -0.2f);
           vec2s[2] = new Vec2(-0.28f,-0.88f);
           vec2s[3] = new Vec2(0.4f,-0.6f);
           vec2s[4] = new Vec2(0.88f,-0.1f);
           vec2s[5] = new Vec2(0.4f,0.82f);
           pd.set(vec2s, 6);
          
           FixtureDef fd = new FixtureDef();
           fd.shape = pd;
           fd.density = 1;
           fd.friction = 0.8f;
           fd.restitution = 0.3f;
          
           BodyDef db= new BodyDef();
           db.position.set(pos/RATE, (ScreenH-FLOOR_HEIGHT-50f)/RATE);
           db.type = BodyType.DYNAMIC;
           db.bullet = true; //表示這是個高速運轉的物體,需要精細的模擬
          
           Body body = world.createBody(db);
           body.m_userData = new Bullet(bulletBitmap, pos, FLOOR_HEIGHT+15.0f,30,30, 0);
           body.createFixture(fd);
          
           bullet.add(body);
        }
    }
}
複製代碼

子彈的物體創建完成了,接下來就需要在logic()與draw()方法中進行子彈的邏輯模擬以及繪畫,在這裏就不在贅述。

此時可以運行遊戲,查看一下效果。可以看到遊戲開始,子彈在半空中下落到地面。與現實世界似乎相同。

2.     子彈上膛

現在已經成功把子彈添加到了模擬世界中。接下來我們要讓子彈上膛,讓子彈和發射器綁定在一起。這時候我們需要引進第三個關節---焊接關節。顧名思義,就是我們需要把子彈焊接在發射器上。

首先創建所需要的變量。

private WeldJoint wj;//焊接關節

然後創建createWeldJoint()創建焊接關節的方法。

複製代碼
//創建焊接關節
    public WeldJoint createWeldJoint() {
       Body body;
       Iterator<Body> aIterator = bullet.iterator(); //使用迭代器取出set集合中的數據
       while (aIterator.hasNext()) {   //判斷時候還有數據
           body = aIterator.next(); //獲取下一個數據,第一次是獲取第一個數據
           body.setTransform(new Vec2((360f/RATE), (ScreenH-FLOOR_HEIGHT-bulletBitmap.getHeight()-227)/RATE), 0);
            WeldJointDef wd = new WeldJointDef();
            wd.initialize(body, catapultArmBody, catapultArmBody.getWorldCenter());
            return (WeldJoint) world.createJoint(wd);
       }
       return null;
    }
複製代碼

方法創建完成之後,在surfaceCreated()方法中調用。

wj = createWeldJoint();

此時焊接關節創建完成。運行遊戲。可以看到效果。

3.     發射子彈

此時子彈已經上膛了。可以推動發射器看一下效果。子彈可以跟隨發射器一起移動。但是這也不是我們想要的效果。我們需要的效果是推動發射器,然後發射器復原的時候憑藉恢復力把子彈發射出去。接下來就去完成發射子彈的功能。

完成這個功能我們之需要在發射器恢復到一定角度的時候,銷燬焊接關節,使子彈脫離發射器。這樣就可以完成子彈的發射。

首先創建所需要的變量。

private boolean catapult_flag = false;//推動發射器標示

這個變量的目的用於防治觸摸到發射器,變使子彈發射的bug。只有推動發射器到達一定角度是,纔算推動了發射器。

接下來需要在logic()邏輯方法中,進行判斷。

複製代碼
//推動發射器到一定一角度
       if(catapultArmBody.getAngle()< - (float) (30f*Math.PI/180))
    {
        catapult_flag=true;
    }
      
       if(wj != null&&catapult_flag)
        {
        if(catapultArmBody.getAngle()>=-(float) (10f*Math.PI/180)){
            world.destroyJoint(wj);//銷燬焊接關節
            wj = null;
        }
        }
複製代碼

這裏我們默認只有推動發射器到達30°的時候才能發射子彈。並且當發射器恢復到10°的時候,銷燬焊接關節。此時子彈發出。運行遊戲可以看下效果。

4.子彈續膛

當一個子彈被我們發射出去之後,問題也就隨之而來了。對!剩下的子彈怎麼辦。我們接下來就完成,子彈續膛!

這裏需要考慮兩個問題。

  1. 何時銷燬已經發射的子彈?
  2. 何時讓新的子彈續膛?

何時銷燬子彈,可以設定兩種情況,第一種當子彈超出場景的範圍,第二種當子彈在場景內靜止時。這兩種情況滿足一種便可銷燬子彈。

 何時讓薪資單續膛,這裏考慮兩種情況,第一種當前一個子彈脫離發射器時續膛。第二種是當前一個子彈銷燬時續膛。這裏第一種情況會出現一個bug。當前一個子彈脫離發射器,續膛的子彈會瞬間與發射器進行焊接,這樣會影響前一個子彈的運行軌道。所以在這裏才需第二種方式。

 首先定義變量。

private boolean moveing_flag = false; //子彈是否處於移動狀態

接下來就是要判斷髮射的子彈時候靜止或者超出了場景範圍,需要在logic方法中進行判斷。

複製代碼
if(bullet.iterator().hasNext())//首先判斷時候還有爲發射的子彈
       {
           //只要發射的子彈靜止或者超出了場景範圍就執行
       if(!bullet.iterator().next().isAwake()||bullet.iterator().next().getPosition().x*RATE>background_bottom.getWidth())
        {
              moveing_flag = false;
        }
       }
複製代碼

並且要在銷燬焊接關節的方法中,加入一條語句。是moveing_flag初始化。

moveing_flag = true;

然後我們在logic方法中編寫子彈續膛的方法。

複製代碼
//子彈續膛
    if(wj == null&&!bullet.isEmpty()&&!moveing_flag)
    {
        //銷燬已經發出去的子彈
        world.destroyBody(bullet.iterator().next());
        bullet.remove(bullet.iterator().next());
        catapult_flag = false;
        wj = createWeldJoint();//創建新的焊接關節
    }
複製代碼

此時子彈續膛的功能已經完成。可以運行遊戲進行測試。

下一章節,我們將創建移動的鏡頭,添加目標。盡請期待!~~

 

 

 

 

 

 

 

 


發佈了12 篇原創文章 · 獲贊 1 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章