package com.cookbook.samples; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Input; import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.math.Vector3; import com.badlogic.gdx.physics.box2d.Body; import com.badlogic.gdx.physics.box2d.BodyDef; import com.badlogic.gdx.physics.box2d.BodyDef.BodyType; import com.badlogic.gdx.physics.box2d.Box2DDebugRenderer; import com.badlogic.gdx.physics.box2d.CircleShape; import com.badlogic.gdx.physics.box2d.FixtureDef; import com.badlogic.gdx.physics.box2d.PolygonShape; import com.badlogic.gdx.physics.box2d.World; import com.badlogic.gdx.utils.viewport.FitViewport; import com.badlogic.gdx.utils.viewport.Viewport; public class Box2DSimpleSample extends GdxSample { private static final String TAG = "Box2DSimpleSample"; private static final float SCENE_WIDTH = 12.8f; // 13 metres wide private static final float SCENE_HEIGHT = 7.2f; // 7 metres high private Viewport viewport; private Vector3 point = new Vector3(); private SpriteBatch batch; // General Box2D Box2DDebugRenderer debugRenderer; BodyDef defaultDynamicBodyDef; World world; // Squares FixtureDef boxFixtureDef; PolygonShape square; // Circles CircleShape circle; FixtureDef circleFixtureDef; //To switch between boxes and balls boolean boxMode = true; @Override public void create () { super.create(); viewport = new FitViewport(SCENE_WIDTH, SCENE_HEIGHT); // Center camera to get (0,0) as the origin of the Box2D world viewport.getCamera().position.set(viewport.getCamera().position.x + SCENE_WIDTH*0.5f, viewport.getCamera().position.y + SCENE_HEIGHT*0.5f , 0); viewport.getCamera().update(); batch = new SpriteBatch(); Gdx.input.setInputProcessor(this); // Create Physics World world = new World(new Vector2(0,-9.8f), true); // Tweak debug information debugRenderer = new Box2DDebugRenderer( true, /* draw bodies */ false, /* don't draw joints */ true, /* draw aabbs */ true, /* draw inactive bodies */ false, /* don't draw velocities */ true /* draw contacts */); // Creates a ground to avoid objects falling forever createGround(); // Default Body Definition defaultDynamicBodyDef = new BodyDef(); defaultDynamicBodyDef.type = BodyType.DynamicBody; // Shape for square square = new PolygonShape(); // 1 meter-sided square square.setAsBox(0.5f, 0.5f); // Shape for circles circle = new CircleShape(); // 0.5 metres for radius circle.setRadius(0.5f); // Fixture definition for our shapes boxFixtureDef = new FixtureDef(); boxFixtureDef.shape = square; boxFixtureDef.density = 0.8f; boxFixtureDef.friction = 0.8f; boxFixtureDef.restitution = 0.15f; // Fixture definition for our shapes circleFixtureDef = new FixtureDef(); circleFixtureDef.shape = circle; circleFixtureDef.density = 0.5f; circleFixtureDef.friction = 0.4f; circleFixtureDef.restitution = 0.6f; } @Override public boolean touchDown (int screenX, int screenY, int pointer, int button) { if (button == Input.Buttons.LEFT) { //Translate screen coordinates into world units viewport.getCamera().unproject(point.set(screenX, screenY, 0)); if(boxMode) createSquare(point.x,point.y); else // Circle mode createCircle(point.x,point.y); boxMode = !boxMode; return true; } return false; } private void createSquare(float x, float y) { defaultDynamicBodyDef.position.set(x,y); Body body = world.createBody(defaultDynamicBodyDef); body.createFixture(boxFixtureDef); } private void createCircle(float x, float y) { defaultDynamicBodyDef.position.set(x,y); Body body = world.createBody(defaultDynamicBodyDef); body.createFixture(circleFixtureDef); } private void createGround() { float halfGroundWidth = SCENE_WIDTH; float halfGroundHeight = 0.5f; // 1 meter high // Create a static body definition BodyDef groundBodyDef = new BodyDef(); groundBodyDef.type = BodyType.StaticBody; // Set the ground position groundBodyDef.position.set(halfGroundWidth*0.5f, halfGroundHeight); // Create a body from the defintion and add it to the world Body groundBody = world.createBody(groundBodyDef); // Create a rectangle shape which will fit the world_width and 1 meter high // (setAsBox takes half-width and half-height as arguments) PolygonShape groundBox = new PolygonShape(); groundBox.setAsBox(halfGroundWidth * 0.5f, halfGroundHeight); // Create a fixture from our rectangle shape and add it to our ground body groundBody.createFixture(groundBox, 0.0f); // Free resources groundBox.dispose(); } @Override public void resize(int width, int height) { viewport.update(width, height); } @Override public void dispose() { debugRenderer.dispose(); batch.dispose(); square.dispose(); circle.dispose(); world.dispose(); } @Override public void render () { Gdx.gl.glClearColor(0, 0, 0, 1); Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); // If the game doesn't render at 60fps, the physics will go mental. That'll be covered in Box2DFixedTimeStepSample world.step(1/60f, 6, 2); debugRenderer.render(world, viewport.getCamera().combined); } }