in C++ • Has been used for example in Angry Birds, Tiny Wings • Has been ported to Java, Flash, C#, JavaScript • IDEs / frameworks that use Box2D – libGDX, Unity, iOS SpriteKit, GameMaker Studio ...
interact • Body – Game Objects that contains fixtures – Dynamic (spaceship), Static (ground) and Kinematic – Fixture • Body has Fixture! • Density: Mass per square meter: bowling ball dense, balloon not so • Friction: When sliding along something, amount of opposite force • Restitution: How bouncy object is (0 = does not bounce, 1 = very bouncy) • Shape – Fixture has Shape – Polygon or Circle, can be mixed • Joint – Holds bodies together. Several joints available.
Array<Body> bodies = new Array<Body>(); // Take all bodies from world and put them into array world.getBodies(bodies); // Get shape of first body, it's first fixture and it's shape Shape s = bodies.get(0).getFixtureList().get(0).getShape();
– kilogram – second (KMS) • Optimized so that shapes can move between 0.1 – 10 meters • It's tempting to use pixel as units -> leads to poor simulation and weird behavior – Keep moving objects between 0.1 – 10 meters! • DO NOT USE PIXELS! DO NOT!
Box2D units (meters) • How to handle this? Just use meters in World Units, so you don't have to make any conversions – float width = 640.0f / 100.0f – float height = 400.0f / 100.0f – camera = new OrthographicCamera(); – camera.setToOrtho(false, width, height);
SpriteBatch batch; private World world; @Override public void create() { // Create world and set it's gravity! // true => allow body sleeping. Bodies // are excluded from the simulation until something happens // to 'wake' them again. world = new World(new Vector2(0, -9.8f), true); // Next steps: create a body to the world ... batch = new SpriteBatch(); } @Override public void render() { ... } }
on screen • Static Body – Walls, floors and so on • Kinematic Body – "Moving platform in platform game" – It's a static body that can also move and rotate. When dynamic body collides, kinematic body "wins"
not hold texture! So it's not visible! • Hold properties like – mass, velocity, location, angle • Define size and shape of the body using a fixture – Shape can be circle or polygon or a mixture of these
Body Definition BodyDef myBodyDef = new BodyDef(); // It's a body that moves myBodyDef.type = BodyDef.BodyType.DynamicBody; // Initial position is centered up // This position is the CENTER of the shape! myBodyDef.position.set(WORLD_WIDTH / 2, WORLD_HEIGHT / 2); return myBodyDef; }
playerFixtureDef = new FixtureDef(); // Mass per square meter (kg^m2) playerFixtureDef.density = 1; // How bouncy object? Very bouncy [0,1] playerFixtureDef.restitution = 1.0f; // How slipper object? [0,1] playerFixtureDef.friction = 0.5f; // Create circle shape. CircleShape circleshape = new CircleShape(); circleshape.setRadius(0.5f); // Add the shape to the fixture playerFixtureDef.shape = circleshape; return playerFixtureDef; }
rendering – For every render call, update (step) the world • To render, map some texture to the position of the playerBody! • For debugging, use debugRenderer – debugRenderer.render(world, camera.combined);
tell the world to step // Advance simulation 1/60 of a sec. This should // correspond to frame rate in your game float timeStep = 1/60.0f; // How strongly to correct velocity when colliding // More higher, more correct simulation but cost of performance int velocityIterations = 8; // How strongly to correct position when colliding // More higher, more correct simulation but cost of performance int positionIterations = 3; world.step(timeStep, velocityIterations, positionIterations); • Do this at the end of the render() call
3); • Simulation can be ruined if machine is not able to run at 60fps • You could calculate the game speed and add it to stepping – world.step(Gdx.graphics.getDeltaTime(), 6, 2); • However: – "We also don't like the time step to change much. A variable time step produces variable results, which makes it difficult to debug. So don't tie the time step to your frame rate" • Use fixed time step. In game loop, call the step several times with fixed value!
Add shape to fixture, 0.0f is density. // Using method createFixture(Shape, density) no need // to create FixtureDef object as on createPlayer! groundBody.createFixture(getGroundShape(), 0.0f); } private BodyDef getGroundBodyDef() { // Body Definition BodyDef myBodyDef = new BodyDef(); // This body won't move myBodyDef.type = BodyDef.BodyType.StaticBody; // Initial position is centered up // This position is the CENTER of the shape! myBodyDef.position.set(WORLD_WIDTH / 2, 0.25f); return myBodyDef; } private PolygonShape getGroundShape() { // Create shape PolygonShape groundBox = new PolygonShape(); // Real width and height is 2 X this! groundBox.setAsBox( WORLD_WIDTH / 2 , 0.25f ); return groundBox; }
to apply forces or impulses to a body • Force – Gradually over time change velocity of a body – Also angular force available, torque (twisting strength) • Impulse – Change velocity immediately • Of course you can just change the position of a body