3.Libgdx扩展学习之Box2D_夹具
Posted zqiang_55
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了3.Libgdx扩展学习之Box2D_夹具相关的知识,希望对你有一定的参考价值。
文章中涉及的很多概念,都是来自《Box2D中文手册》。有统一的解释方便理解
夹具
概念介绍
形状不知道物体的存在,并可独立于物理模拟而被使用。因此 Box2D 提供 Fixture 类,用于将形状附加到物体上。一个物体可以有零个或多个 fixture。拥有多个 fixture 的物体有时被叫做组合物体。
fixture具有下列属性:
- 关联的形状
- broad-phase 代理
- 密度(density)、摩擦(friction)、恢复(restitution)
- 碰撞筛选标记(collision filtering flags)
- 指向父物体的指针
- 传感器标记(sensor flag)
创建夹具
创建夹具,必须先初始化和夹具定义FixtureDef,并将定义传到父物体中,
先看夹具定义:
/** A fixture definition is used to create a fixture. This class defines an abstract fixture definition. You can reuse fixture
* definitions safely.
* @author mzechner */
public class FixtureDef
/** The shape, this must be set. The shape will be cloned, so you can create the shape on the stack. */
public Shape shape;
/** The friction coefficient, usually in the range [0,1]. **/
public float friction = 0.2f;
/** The restitution (elasticity) usually in the range [0,1]. **/
public float restitution = 0;
/** The density, usually in kg/m^2. **/
public float density = 0;
/** A sensor shape collects contact information but never generates a collision response. */
public boolean isSensor = false;
/** Contact filtering data. **/
public final Filter filter = new Filter();
上面列出的FixtureDef属性,其实就是上面文字描述的代码形式,在实际操作中我们是这样创建的:
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = circleShape;
fixtureDef.density = 1.0f;
fixtureDef.restitution = 0.6f;
body.createFixture(fixtureDef);
这会创建 fixture,并将它附加到物体之上。不需要保存 fixture 的指针,因为当它的父物体被摧毁时, fixture 也会自动被摧毁。 可以在单个物体上创建多个 fixture。
可以摧毁父物体上的 fixture,来模拟一个可分裂开的物体。
FixtureDef属性介绍
密度(density)
fixture 的密度用来计算父物体的质量属性。密度值可以为零或者是正数。所有的 fixture 都应该使用相似的密度,这样做可以改善堆叠稳定性。
当设置密度的时候,物体的质量不会立即改变。你必须调用 resetMassData ,使之生效。
fixture.setDensity (float density)
body.resetMassData ()
摩擦(friction)
摩擦可以使对象逼真地沿其它对象滑动。摩擦参数通常会设置在 0 到 1 之间,但也可是任意的非负数, 0 意味着没有摩擦, 1 会产生强摩擦。
恢复系数(restitution)
恢复可以使对象弹起。恢复的值通常设置在 0 到 1 之间。想象一个小球掉落到桌子上,值为 0 表示着小球不会弹起, 这称为非弹性碰撞。值为 1 表示小球的速度跟原来一样,只是方向相反,这称为完全弹性碰撞。
筛选(filter)
碰撞筛选是为了防止某些 fixture 之间发生碰撞。比如,创造了一个骑自行车的角色。希望自行车与地形之间有碰撞,角色与地形有碰撞,但你不希望角色和自行车之间发生碰撞 (因为它们必须重叠)。 Box2D 通过种群和分组来支持这样的碰撞筛选。
Box2D 支持 16 个种群。任意 fixture 你都可以指定它属于哪个种群。你还可以指定这个 fixture 可以和其它哪些种群发生碰撞。例如,你可以在一个多人游戏中指定玩家之间不会碰撞,怪物之间也不会碰撞,但是玩家和怪物会发生碰撞。这是通过掩码来完成的,例如:
playerFixtureDef.filter.categoryBits = 0x0002
monsterFixtureDef.filter.categoryBits = 0x0004
playerFixtureDef.filter.maskBits = 0x0004
monsterFixtureDef.filter.maskBits = 0x0002
下面是产生碰撞的规则:
short catA = fixtureA.filter.categoryBits ;
short maskA = fixtureA.filter.maskBits;
short catB = fixtureB.filter.categoryBits
short maskB = fixtureB.filter.maskBits;
if((catA & catB) != 0 && (catB & maskA) != 0)
// fixtures can collide
碰撞分组让你指定一个整数的组索引。你可以融同一个组的所有fixture总是相互碰撞(正索引)或者永远不碰撞(负索引)。组索引通常用于一些以某种方式关联的事物,就像自行车的那些不见。在下面例子中,fixture1和fixture2总是碰撞,而fixture3和fixture4永远不会碰撞
fixture1Def.filter.groupIndex = 2;
fixture2Def.filter.groupIndex = 2;
fixture3Def.filter.groupIndex = -8;
fixture4Def.filter.groupIndex = -8;
如果组索引不同,碰撞筛选会按照种群和掩码来进行。换句话说,分组筛选和种群筛选相比,具有更高的优选级。
注意在Box2D中还有其它的碰撞筛选,这里有一个列表:
- static上的fixture只会与dynamic物体上的fixture发生碰撞
- kinematic物体只会和dynamic物体发生碰撞
- 同一个物体上的fixture永远不会相互碰撞
- 如果两个物体用关节连接起来,物体上面的fixture可以选择启用或者禁止它们之间的相互碰撞
传感器
有时候游戏逻辑需要判断两个 fixture 是否相交,而不想有碰撞反应。这可以通过传感器(sensor)来完成。传感器也是个 fixture,但它只会侦测碰撞,而不产生其它反应。
可以将任意 fixture 标记为传感器。传感器可以是 static、 kinematic 或 dynamic 的。记住,每个物体上可以有多个 fixture,传感器和实体 fixture 是可以混合存在的。而且,只有至少一个物体是dynamic 的,传感器才会产生接触事件,而 kinematic 与 kinematic 、 kinematic 与 static ,或者static 与 static 之间都不会产生接触事件。
public class BodyShapeA extends ApplicationAdapter
World world;
Box2DDebugRenderer box2DDebugRenderer;
OrthographicCamera camera;
float scene_width = 12.8f;
float scene_height = 7.2f;
@Override
public void create()
world = new World(new Vector2(0.0f, -9.8f), true);
box2DDebugRenderer = new Box2DDebugRenderer();
camera = new OrthographicCamera(scene_width, scene_height);
camera.position.set(scene_width / 2, scene_height / 2, 0);
camera.update();
createStaticBox();
Gdx.input.setInputProcessor(new InputHandA());
@Override
public void render()
world.step( 1/ 60f, 6, 2);
Gdx.gl.glClearColor(0.39f, 0.58f, 0.92f, 1.0f);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
box2DDebugRenderer.render(world, camera.combined);
@Override
public void dispose()
world.dispose();
box2DDebugRenderer.dispose();
private void createStaticBox()
// 创建地面
createBorderBox(scene_width * 0.5f, 0.2f, scene_width * 0.5f, 0.2f, 0);
// 创建倾斜矩形,这里创建矩形,然后用angle来控制
createBorderBox(3.0f, 5.0f, 0.1f, 1.3f, MathUtils.PI / 3);
// 创建池子
createBorderBox(5.0f, 2.5f, 0.1f, 1.0f, 0);
createBorderBox(9.0f, 2.5f, 0.1f, 1.0f, 0);
createBorderBox(7.0f, 1.6f, 2.1f, 0.1f, 0);
private void createBorderBox(float px, float py, float w, float h, float angle)
BodyDef bodyDef = new BodyDef();
bodyDef.position.set(px, py);
bodyDef.angle = angle;
Body body = world.createBody(bodyDef);
PolygonShape polygonShape = new PolygonShape();
polygonShape.setAsBox(w, h);
body.createFixture(polygonShape, 0);
polygonShape.dispose();
private void createCircle(float x, float y)
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyDef.BodyType.DynamicBody;
bodyDef.position.set(x, y);
Body body = world.createBody(bodyDef);
CircleShape circleShape = new CircleShape();
circleShape.setRadius(0.2f);
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = circleShape;
fixtureDef.density = 1.0f;
fixtureDef.restitution = 0.6f;
body.createFixture(fixtureDef);
circleShape.dispose();
private class InputHandA extends InputAdapter
@Override
public boolean touchDown(int screenX, int screenY, int pointer, int button)
// 在屏幕点击出创建响应的圆形Body
Vector3 vector3 = new Vector3(screenX, screenY, 0);
camera.unproject(vector3);
createCircle(vector3.x, vector3.y);
return true;
以上是关于3.Libgdx扩展学习之Box2D_夹具的主要内容,如果未能解决你的问题,请参考以下文章