使用libgdx对Box2D进行封装:flixel-gdx-box2d
FlxBox2D是一个通过使用libgdx对Box2D进行封装,它使得在flixel中使用Box2D编写代码变得更加简单。
Getting started
Before you start writing code with Box2D it is recommended you read the manual first. Box2D is not something simple to start off directly. The manual can be downloaded here: http://box2d.org/manual.pdf. If you don’t like reading the manual, there is also a website that teaches you from scratch: http://www.iforce2d.net/b2dtut/introductions. Either way, you shouldn’t proceed if you haven’t read the stuff.
Things you need to know about FlxBox2D
The prefix of FlxBox2D classes begins with B2Flx
. Some variables are already set as default or differ from Box2D. The table below shows which.
B2FlxB.RATIO (32f) | The ratio from meters to pixels. |
B2FlxB._gravity (0, 9.8f) | The gravity. |
B2FlxB.contact | The contact manager used for collision detection is intiliazed on setup. |
B2FlxShape.resetAngle (true) | Resets the angle to 0 when it reaches 360 or -360 to prevent overflow. |
Radians to Degrees | Box2D uses radians, but FlxBox2D converts them to degrees. |
To get Box2D objects working your state needs to inherit B2FlxState
instead FlxState
. The World
will be created in B2FlxState
and this will also avoid the spiral of death, because flixel uses delta time step while Box2D uses fixed time step. B2FlxState
solves this by using fixed delta time step.
Depending on your game requirements, choose one of the collision algorithms and don’t mix them.
Shapes
If you’ve read the manual, then you saw some snippets how to create a shape. It requires a fixture and body definition before it finally become a body that can freely move in the world. Fortunately FlxBox2D significantly simplify instantiation of bodies and provide a simple way to skin bodies with custom graphics.
Box shape
new B2FlxBox(50,50, 50, 50) .setRestitution(.3f) .setFriction(.2f) .setDensity(.8f) .setDraggable(true) .create();
To make the body alive in world you need call create()
at the end. There are five different shapes you can create.
Combining shapes together is also possible. You need to create a shapeless Shape and create fixtures from other shapes.
// Shapeless. Attach shapes to it. B2FlxSprite sprite = new B2FlxSprite(200, 200).create(); B2FlxPolygon polyshape = new B2FlxPolygon(0, 0, new float[][][] { {{-64,-64},{32,-32},{32,32},{-32,32}} }) .setRestitution(.3f) .setFriction(.2f) .setDensity(.8f); sprite.createFixtureFromPolygon(polyshape, true);
Class diagram of shapes
Joints
There are 10 different joints. All of them are created about the same way.
B2FlxBox box1 = createBox(25, 25, 50, 50); B2FlxBox box2 = createBox(100, 25, 50, 50); new B2FlxDistanceJoint(box1, box2) .setAnchorA(box1.body.getWorldCenter()) .setAnchorB(box2.body.getWorldCenter()) .setShowLine(true) .create();
Read the manual what a specific joint does and is used for.
Class diagram of joints
Debug
To enable to debug mode, you need to set FlxG.debug
to true in your class that extends FlxGame
. The debug settings can be found in B2FlxDebug
.
Note: the boundingbox of FlxSprite
is not visible anymore when using Box2D objects.
Collision usage in FlxBox2D
At default the fixtures are able to collide with other fixtures, but it’s also possible to setup collision filters to have a better control over which fixtures can collide with each other. The collision filter has three variables:
categoryBits | The shape that belongs to. |
maskBits | This states the categories that this shape would accept for collision. I'm categoryBits and collide with MaskBits. |
groupIndex | Collision groups allow a certain group of objects to never collide (negative) or always collide (positive). Zero means no collision group. Non-zero group filtering always wins against the mask bits. |
This tutorial (http://www.aurelienribon.com/blog/2011/07/box2d-tutorial-collision-filtering/) clearly tells how collision in Box2D works and it’s recommended you read this first.
The collision in Box2D happens with a listener. This means the collision check mustn’t be put inside the update loop. The event listener is created on default when B2FlxState
is initialized. In FlxBox2D the B2FlxContactManager
makes things a little easier. The only things you need to do are choosing the contact type and pass the categoryBits
or groupIndex
and the callback. Take a look below for an example.
short PLAYER = 0x0001; short ENEMY = 0x0002; B2FlxBox player = new B2FlxBox(8, 10, 64, 64) .setGroupIndex(1) .setCategoryBits(PLAYER) .setMaskBits(ENEMY) .create(); B2FlxBox enemy = new B2FlxBox(20, 10, 64, 64) .setGroupIndex(1) .setCategoryBits(ENEMY) .setMaskBits(PLAYER) .create(); B2FlxB.contact.onBeginContact(PLAYER, ENEMY, onHit) IB2FlxLister onHit = new IB2FlxListener() { @Override public void onContact(B2FlxShape sprite1, B2FlxShape sprite2, Contact contact, Manifold oldManifold, ContactImpulse impulse) { sprite1.hurt(); } }
player
object can collide with enemy
object (maskbit ENEMY
vs PLAYER
) and both got positive groupIndex (1)
. This example was single object handling, but you can also collide single against group and group against group. Check this example for the rest of the code.
Examples: