本章源码链接:http://pan.baidu.com/s/1o6Tt6VS密码:dvsc
在本章我们将为Flappy Bird添加BOX2D物理仿真,BOX2D物理仿真可以模拟现实世界物体的属性,如重力、速度、摩擦等等。在BOX2D中存在三种物理对象,分别是StaticBody、KinematicBody和DynamicBody,其中静态物体StaticBody只能模拟那些固定不动的对象且不能与StaticBody和KinematicBody类型物理对象发生碰撞。KinematicBody和StaticBody类似,但是他可以模拟速度,让对象按照一定的速度运动,但他也不能与StaticBody和KinematicBody类型物理对象放生碰撞。最后一种DynamicBody对象既可以模拟所有物理属性,也可以与上述三种类型物体的任意一种发生碰撞。
首先,我们为三个对象添加一个共同的方法,既然是共同的方法,那么我们就应该添加到三者公用的父类中,然后再子类中重写该方法。
修改AbstractGameObject:
package com.art.zok.flappybird.game.object;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.World;
public abstract class AbstractGameObject {
public Vector2 position;
public Vector2 dimension;
public Vector2 origin;
public Vector2 scale;
public float rotation;
public Body body;
public AbstractGameObject() {
position = new Vector2();
dimension = new Vector2(1, 1);
origin = new Vector2();
scale = new Vector2(1, 1);
rotation = 0;
}
public void beginToSimulate(World world) {
}
public void update(float deltaTime) {
if(body != null) {
position.set(body.getPosition());
rotation = body.getAngle() * MathUtils.radiansToDegrees;
}
}
public abstract void render(SpriteBatch batch);
}
上面我们为AbstractGameObject类添加了一个公有的beginToSimulate()方法。我们在每个子类重写该方法,并在其中添加创建BOX2D物理世界的Body对象代码。
为对象创建Body
首先,我们为Bird对象重写beginToSimulate()方法:
@Override
public void beginToSimulate(World world) {
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyType.DynamicBody; // 必须是动态对象
bodyDef.fixedRotation = true; // 固定角度
bodyDef.position.set(position);
body = world.createBody(bodyDef);
body.setUserData(this);
PolygonShape shape = new PolygonShape();
shape.setAsBox(dimension.x / 2, dimension.y / 2);
shape.setRadius(-0.4f);
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.density = 0.1f;
fixtureDef.friction = 0f;
fixtureDef.shape = shape;
body.createFixture(fixtureDef);
}
这里我们首先介绍一下World参数,World表示BOX2D中模拟世界,所有在该世界创建的Body对象都会作为模拟对象,因此,只要我们要使用BOX2D那么绝离不开World。接下来是BodyDef,BodyDef是创建Body对象所要使用的参数,该参数定义了Body的类型、位置以及各种属性参数。这里我们将Bird对象定义为DynamicBody类型,fixedRotiation=ture表示我们不使用BOX2D模拟Bird对象的旋转过程,Bird对象的旋转角度一直为0。接下来我们初始化了Body的位置。下面我们使用World.createBody()创建了body对象,并将其付给成员变量body。PolygonSape描述的是BOX2D中多边形物体的形状,BOX2D规定PolygonSape必须是凸多边形,并且最多是八条边,如果是凹多边形或者大于八条边的多边形就需要使用网格化技术等等各种技术,还要我们这里并不牵扯这么复杂的问题,因为我们只需要将Bird当作四条边的矩形即可。所以我们使用了setAsBox()方法将该多边形设置为一个宽高分别为dimension.x和dimension.y,注意这里的两个参数分别是半宽和半高。setAsBox()还有一个重载方法setAsBox(hx, hy, center, angle)其中center表示矩形的中心点,该点坐标值是以position为原点的坐标系为标准的,angle表示旋转角度。所以setAsBox(hx, hy)默认以(0, 0)为中心点,旋转角度为0。setRadius(-0.4f)是为避免发生隧道效应而设置的,该值可以理解为碰撞时的最大碰撞深度,我们设定为负值只是为了让游戏更加逼真而已,也降低了一定的难度。FixtureDef定义了Body的物理属性参数,如密度、摩擦力和形状等等。接下来我们使用该参数为Body创建Fixture对象。还有Body.setUserData()可以为Body对象设定一个用户自定义数据,我们这里传递了this,