基于JBox2D物理引擎开发的“雷电”小游戏(二)——创建世界

在上一篇文章中,我给出了几张游戏的图片,相信大家已经迫不及待想要知道这个是如何实现的吧,OK,下面我从最基础的部分开始讲。

创建世界

在使用JBox2D物理引擎时,我们需要先创建一个world,在这个world下,我们可以创建出我们想要的刚体,既然是创建一个world,那么就需要给这个world定下world的尺寸大小。
下面先看看代码吧:

public class MainActivity extends Activity implements View.OnClickListener{
    //屏幕到现实世界的比例 10px:1m;这里要注意,当我们根据android当中的坐标去定义刚体的位置时,
    // 我们需要将坐标除以这个比例获得世界当中的长度,用这个长度来进行定义。
    private final static int RATE = 10;
    //创建一个坐标系统
    private AABB worldAABB;
    //创建一个世界
    public static World world;
    ...
    public void createWorld(){
        //创建这个世界的坐标范围,并且设定上下限,这里应该是按世界的长度来算的,
        //也就是说这个范围是足够大的,我们只能在这个范围内创建刚体
        worldAABB = new AABB();
        //第一个参数为左边界参数,第二个参数为上边界参数,按世界的长度来算
        worldAABB.lowerBound.set(-200.0f, -200.0f);
        //第一个参数为右边界参数,第二个参数为下边界参数,按世界的长度来算
        worldAABB.upperBound.set(200f, 300.0f);
        //向量,用来标示当前世界的重力方向,第一个参数为水平方向,
        //负数为做,正数为右。第二个参数表示垂直方向
        Vec2 gravity = new Vec2(0.0f, 10.0f);
        //标示 是否睡眠
        boolean doSleep = true;
        //创建世界
        world = new World(worldAABB, gravity, doSleep);
        ...
    }
    ...
}

代码中的注释写的很详尽了,我也不多作解释了。

创建边界

虽然已经创建好了世界,不过如果不给世界创建边界的话,刚体会掉出世界外哦,一旦掉出世界,刚体便不会再遵循原本世界的法则(重力等),小伙伴们可以尝试一下。
创建边界前,我们先理解下什么是边界。边界,就是一个能够拦住刚体掉出世界的刚体,简单的来说,边界就是世界中的墙壁,用墙壁将世界中的刚体围起来,这样就不会掉出世界了。
理解了什么是边界后就好办了,我们可以通过创建4个刚体(上边界、下边界、左边界、右边界)来作为边界。

创建刚体类MyBody

在创建刚体时,我们选择面向对象的方法,所以我们先创建一个刚体根类——Mybody类

public abstract class MyBody {//自定义刚体根类
        Body body;//JBox2D物理引擎中的刚体
        int color; //刚体的颜色
        boolean isLive = true; //是否绘制
        boolean isDeleted = false;  //是否被删除

        public abstract void drawSelf(Canvas canvas, Paint paint); //绘制的方法
    }

当然,这个类中没有什么具体的实现方法,代码中的drawSelf方法在稍后会讲到。

创建刚体类MyRectColor

有了刚体根类,下面我们来创建一个矩形刚体的类

public class MyRectColor extends MyBody
    {//自定义的矩形类
        float halfWidth; //半宽
        float halfHeight;  //半高
        boolean isObstacle; //是否为敌人
        boolean isBottom;//是否为底边
        boolean isTop;//是否为上边
        boolean isLeft;//是否为左边界
        boolean isRight;//是否为右边界
        int level;//敌人的等级
        ...

        public MyRectColor(Body body, float halfWidth, float halfHeight, int color, 
                            boolean isObstacle,boolean isBottom,boolean isTop,
                            boolean isLeft,boolean isRight,int level) {
            //以下为初始化成员变量
            this.body = body;   
            this.halfWidth = halfWidth; 
            this.halfHeight = halfHeight; 
            this.color = color;  
            this.isObstacle = isObstacle; 
            this.isBottom = isBottom;
            this.isTop = isTop;
            this.isLeft = isLeft;
            this.isRight = isRight;
            this.level = level; 
            ...
        }

        public void drawSelf(Canvas canvas, Paint paint) {//重写的绘制方法
            if (!isLive) {
                return;
            }//如果isLive为false则返回
            float x = body.getPosition().x * RATE;//获取刚体的x坐标
            float y = body.getPosition().y * RATE;//获取刚体的y坐标
            canvas.drawRect(x - halfWidth, y - halfHeight, x + halfWidth, y + halfHeight, paint);
            paint.setStyle(Paint.Style.STROKE);//设置画笔样式
            paint.setStrokeWidth(1);//设置画笔宽度
            paint.setColor(color);//设置颜色
            canvas.drawRect(x - halfWidth, y - halfHeight, x + halfWidth, y + halfHeight, paint);//绘制边
            paint.reset();//恢复画笔设置
            ...
        }
    }

到这里MyRectColor类也已经创建好,这个类继承MyBody类的,看到这里想必也知道drawSelf函数的作用了,即用画笔将刚体画在画布上呈现给用户,对于canvas的使用这里就不做说明了。
在drawSelf函数中,通过body.getPosition().x获取到的坐标为世界中的坐标,要乘以RATE才会得到实际坐标,所以千万不要忘记乘以RATE!!

创建createBox函数

有了MyRectColor类,现在我们需要将其创建出来,所以需要自己再创建一个创建MyRectColor刚体的函数

public MyRectColor createBox( //创建矩形物体(颜色)
                                      float x, //x坐标
                                      float y, //y坐标
                                      float halfWidth, //半宽
                                      float halfHeight, //半高
                                      boolean isObstacle, //是否为敌人
                                      boolean isBottom,//是否为下边界
                                      boolean isTop,//是否为上边界
                                      boolean isLeft,//是否为左边界
                                      boolean isRight,//是否为右边界
                                      World world, //世界
                                      int color,//颜色
                                      int level,//敌人等级
                                      boolean isSensor)//是否产生碰撞反应
        {
            PolygonDef shape = new PolygonDef(); //创建多边形描述对象
            if (!isObstacle) {  //判断isStatic是否为true
                shape.density = 0;  //密度为0
            } else {
                shape.density = 100.0f;  //密度为1.0f
            }
            shape.friction = 0.5f;//设置摩擦系数
            shape.restitution = 1.0f; //设置能量损失率
            shape.isSensor = isSensor;//设置是否产生碰撞反应
            shape.setAsBox(halfWidth / RATE, halfHeight / RATE);
            BodyDef bodyDef = new BodyDef(); //创建刚体描述对象
            bodyDef.position.set(x / RATE, y / RATE); //设置位置
            Body bodyTemp;//定义一个bodyTemp
            while ((bodyTemp = world.createBody(bodyDef)) == null) ; //在世界中创建刚体
            bodyTemp.createShape(shape);  //指定刚体形状
            bodyTemp.setMassFromShapes(); //设置物体质量
            return new MyRectColor(bodyTemp, halfWidth, halfHeight, color, 
                                  isObstacle, isBottom,isTop,isLeft,isRight,level);
        }

通过isObstacle的值判断创建的是否是边界,是边界的话将其密度设置为0,学过物理的话就应该明白密度为0的物体以为没有质量,没有质量意味着运动状态不会被改变,所以设置为0的目的在于将边界定死在我们设置的位置上,不会因为受力而改变位置。
要注意的是,创建刚体时,使用坐标为刚体的中心坐标,创建矩形时,使用的长度为矩形的半长半宽。其中isSensor这个值决定了此刚体是否产生碰撞反应,若设置为true,则在碰到其他刚体时,不会发生碰撞,而是直接穿过刚体,这个值默认为false。

创建边界

前期的准备工作都已经做好,现在就让我们创建出世界的边界吧

public ArrayList<MyBody> bl = new ArrayList<MyBody>();
...
public void createWorld(){
        //创建一个上边界
        MyRectColor TopBorder = createBox(SCREEN_WIDTH/2,-350,SCREEN_WIDTH/2,1,
                        false,false,true,false,false, world,Color.CYAN,0,false);
        //创建一个下边界
        MyRectColor BottomBorder = createBox(SCREEN_WIDTH/2,SCREEN_HEIGHT+140,SCREEN_WIDTH/2,1,
                        false,true,false,false,false, world,Color.CYAN,0,false);
        //创建一个左边界
        MyRectColor LeftBorder = createBox(-1,SCREEN_HEIGHT/2,1,SCREEN_HEIGHT/2,
                        false,false,false,true,false,world,Color.CYAN,0,false);
        //创建一个右边界
        MyRectColor RightBorder = createBox(SCREEN_WIDTH+1,SCREEN_HEIGHT/2,1,SCREEN_HEIGHT/2,
                        false,false,false,false,true,world,Color.CYAN,0,false);
        bl.add(TopBorder);
        bl.add(BottomBorder);
        bl.add(LeftBorder);
        bl.add(RightBorder);
        ...
    }
    ...

bl变量是用于存储所建立的刚体类的,方便我们之后的刚体遍历。
OK,这样就成功的建立出了世界的边界,成功的将世界围起来啦。当然,只是这样,程序是不能开始模拟这个世界的,因为现在只是创建好了一个地形,但却没有让世界开始运转,不过不要着急,我会在下篇文章中详细告诉大家的^_^~

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值