zoukankan      html  css  js  c++  java
  • 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();//创建新的焊接关节
        }

    此时子弹续膛的功能已经完成。可以运行游戏进行测试。

    下一章节,我们将创建移动的镜头,添加目标。尽请期待!~~

     

     

     

     

     

     

     

     

     

  • 相关阅读:
    I/O工作机制
    Apache和Tomcat区别
    jenkins学习和使用
    小程序富文本转化插件
    一个正则表达式的用法
    contenteditable="true"让div可编辑
    JS实现品字布局
    扯扯小程序。
    (canvas)两小球碰撞后的速度问题研究
    canvas画多边形
  • 原文地址:https://www.cnblogs.com/81du/p/2799017.html
Copyright © 2011-2022 走看看