Physical frenzy

    Good afternoon, dear reader! I, a beginner Java programmer, for a long time could not get used to the Box2D library. Firstly, due to the fact that it was written for C ++, and there is no documentation for it, and I do not know the C syntax. Secondly, due to the fact that detailed lessons on this library are only available as an extension of libGDX. After a couple of weeks of hard struggle, I was finally able to understand how to work with this library, and in this article I will talk about it (and show it).

    I work in Eclipse , the article will be connected with this development environment. To get started, download the libGDX collector and make a standard build. We need a Desktop application with the extension Box2D. Then go to Eclipse, click File → Import → Gradle → Gradle Project and specify the path to your assembly.

    Here is a picture showing how mine looks. I added the Utils package with the Constants class to the Core folder, which contains only one constant - the number of pixels per meter. This is so that the world is not gigantic.

    image


    Here is the code for the DesktopLauncher class from com.mygdx.game.desktop:

    Paste this code into the class and forget about it
    package com.mygdx.game.desktop;
    import com.badlogic.gdx.backends.lwjgl.LwjglApplication;
    import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration;
    import com.mygdx.game.MyGdxGame;
    public class DesktopLauncher {
    	public static void main(String[] arg) {
    		LwjglApplicationConfiguration config = new LwjglApplicationConfiguration();
    		// ширина окна
    		config.width = 720;
    		// высота окна
    		config.height = 480;
    		config.backgroundFPS = 60;
    		config.foregroundFPS = 60;
    		new LwjglApplication(new MyGdxGame(), config);
    	}
    }
    


    There will be a lot of code, so I will enclose it in spoilers. Only the MyGdxGame class from the com.mygdx.game package is changed.

    So, let's try to do a fairly simple thing in our application. The path of the ball crashes into the wall from the planks, and they scatter. Something like:

    image


    Idea 1. Bowling
    package com.mygdx.game;
    import com.badlogic.gdx.ApplicationAdapter;
    import com.badlogic.gdx.Gdx;
    import com.badlogic.gdx.Input.Keys;
    import com.badlogic.gdx.graphics.GL20;
    import com.badlogic.gdx.graphics.OrthographicCamera;
    import com.badlogic.gdx.graphics.Texture;
    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.Box2DDebugRenderer;
    import com.badlogic.gdx.physics.box2d.CircleShape;
    import com.badlogic.gdx.physics.box2d.PolygonShape;
    import com.badlogic.gdx.physics.box2d.World;
    import utils.Constants;
    public class MyGdxGame extends ApplicationAdapter {
    	SpriteBatch batch;
    	Texture img;
    	private OrthographicCamera camera;
    	private boolean DEBUG = false;
    	private World world;
    	private Body ball;
    	private Body floor;
    	private Body wall;
    	private Body verticals;
    	private Body horizontals;
    	private Box2DDebugRenderer b2dr;
    	// здесь происходит создание мира и его наполнение
    	public void create() {
    		float w = Gdx.graphics.getWidth();
    		float h = Gdx.graphics.getHeight();
    		camera = new OrthographicCamera();
    		camera.setToOrtho(false, w / 2, h / 2);
    		world = new World(new Vector2(0, -9.8f), false);
    		// мир со стандартной силой тяжести
    		b2dr = new Box2DDebugRenderer();
    		// здесь создается мячик
    		ball = createPlayer();
    		// здесь создается "пол", чтобы все не проваливалось
    		floor = createfloor();
    		// здесь создаются дощечки
    		verticals = createverticals(80, 80);
    		verticals = createverticals(100, 80);
    		verticals = createverticals(120, 80);
    		verticals = createverticals(90, 111);
    		verticals = createverticals(110, 111);
    		verticals = createverticals(100, 141);
    		horizontals = createhorizontals(85, 95);
    		horizontals = createhorizontals(115, 95);
    		horizontals = createhorizontals(100, 126);
    		// здесь создаются стены-ограничители
    		wall = createwall(430, 170);
    		wall = createwall(-430, 170);
    	}
    	public void render() {
    		update(Gdx.graphics.getDeltaTime());
    		// просто черный экран
    		Gdx.gl.glClearColor(0, 0, 0, 1);
    		Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
    		b2dr.render(world, camera.combined.scl(Constants.PPM));
    	}
    	public void resize(int width, int height) {
    		camera.setToOrtho(false, width / 2, height / 2);
    	}
    	public void dispose() {
    		world.dispose();
    		b2dr.dispose();
    	}
    	// обновление мира и камеры
    	public void update(float delta) {
    		world.step(1 / 60f, 6, 2);
    		inputUpdate(delta);
    		cameraUpdate(delta);
    	}
    	// обработка нажатия клавиши пробел
    	public void inputUpdate(float delta) {
    		int HF = 0;
    		if (Gdx.input.isKeyPressed(Keys.SPACE)) {
    			HF = 5;
    		}
    		ball.setLinearVelocity(HF * 5, ball.getLinearVelocity().y);
    	}
    	// камера повсюду следует за мячиком
    	public void cameraUpdate(float delta) {
    		Vector3 position = camera.position;
    		position.x = ball.getPosition().x * Constants.PPM;
    		position.y = ball.getPosition().y * Constants.PPM;
    		camera.position.set(position);
    		camera.update();
    	}
    	// обратите внимание, что не заданы такие параметры, как коэффициент трения,
    	// масса, коэффициент упругости.
    	// мячик и его параметры
    	public Body createPlayer() {
    		Body pBody;
    		BodyDef def = new BodyDef();
    		def.type = BodyDef.BodyType.DynamicBody;
    		def.position.set(20 / Constants.PPM, 90 / Constants.PPM);
    		def.fixedRotation = false;
    		pBody = world.createBody(def);
    		CircleShape shape = new CircleShape();
    		shape.setRadius(10 / Constants.PPM);
    		pBody.createFixture(shape, 1.0f);
    		def.bullet = true;
    		shape.dispose();
    		return pBody;
    	}
    	// пол и его параметры
    	public Body createfloor() {
    		Body fBody;
    		BodyDef def = new BodyDef();
    		// тип тела
    		def.type = BodyDef.BodyType.StaticBody;
    		// координата
    		def.position.set(0, 0);
    		// будет вращаться
    		def.fixedRotation = true;
    		fBody = world.createBody(def);
    		PolygonShape shape = new PolygonShape();
    		// его размеры
    		shape.setAsBox(480 / Constants.PPM, 70 / Constants.PPM);
    		fBody.createFixture(shape, 0.001f);
    		shape.dispose();
    		return fBody;
    	}
    	// стены и их параметры
    	public Body createwall(int xo, int yo) {
    		Body fBody;
    		BodyDef def = new BodyDef();
    		def.type = BodyDef.BodyType.StaticBody;
    		def.position.set(xo / Constants.PPM, yo / Constants.PPM);
    		def.fixedRotation = true;
    		fBody = world.createBody(def);
    		PolygonShape shape = new PolygonShape();
    		shape.setAsBox(50 / Constants.PPM, 100 / Constants.PPM);
    		fBody.createFixture(shape, 0.001f);
    		shape.dispose();
    		return fBody;
    	}
    	// вертикальные дощечки
    	public Body createverticals(int xo, int xy) {
    		Body fBody;
    		BodyDef def = new BodyDef();
    		def.type = BodyDef.BodyType.DynamicBody;
    		def.position.set(xo / Constants.PPM, xy / Constants.PPM);
    		def.fixedRotation = false;
    		fBody = world.createBody(def);
    		PolygonShape shape = new PolygonShape();
    		shape.setAsBox(5 / Constants.PPM, 10 / Constants.PPM);
    		fBody.createFixture(shape, 1.0f);
    		def.bullet = true;
    		shape.dispose();
    		return fBody;
    	}
    	// горизонтальные дощечки
    	public Body createhorizontals(int xo, int xy) {
    		Body fBody;
    		BodyDef def = new BodyDef();
    		def.type = BodyDef.BodyType.DynamicBody;
    		def.position.set(xo / Constants.PPM, xy / Constants.PPM);
    		def.fixedRotation = false;
    		fBody = world.createBody(def);
    		PolygonShape shape = new PolygonShape();
    		shape.setAsBox(13 / Constants.PPM, 5 / Constants.PPM);
    		fBody.createFixture(shape, 1.0f);
    		def.bullet = true;
    		shape.dispose();
    		return fBody;
    	}
    }
    


    It turned out great, right? By changing several parameters, you can achieve exactly what you need! And do not write so many lines of code.

    But now I want to see an elastic blow. And let there be more objects on the stage. We get the following result:

    image

    And here is the code:
    package com.mygdx.game;
    import com.badlogic.gdx.ApplicationAdapter;
    import com.badlogic.gdx.Gdx;
    import com.badlogic.gdx.physics.box2d.FixtureDef;
    import com.badlogic.gdx.graphics.GL20;
    import com.badlogic.gdx.graphics.OrthographicCamera;
    import com.badlogic.gdx.graphics.Texture;
    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.Box2DDebugRenderer;
    import com.badlogic.gdx.physics.box2d.CircleShape;
    import com.badlogic.gdx.physics.box2d.PolygonShape;
    import com.badlogic.gdx.physics.box2d.World;
    import utils.Constants;
    public class MyGdxGame extends ApplicationAdapter {
    	SpriteBatch batch;
    	Texture img;
    	private OrthographicCamera camera;
    	private boolean DEBUG = false;
    	private World world;
    	private Body ball;
    	private Body floor;
    	private Body wall;
    	private Body verticals;
    	private Body horizontals;
    	private Box2DDebugRenderer b2dr;
    	public void create() {
    		float w = Gdx.graphics.getWidth();
    		float h = Gdx.graphics.getHeight();
    		camera = new OrthographicCamera();
    		camera.setToOrtho(false, w / 2, h / 2);
    		world = new World(new Vector2(0, -9.8f), false);
    		b2dr = new Box2DDebugRenderer();
    		// наш мячик
    		ball = createPlayer();
    		// границы мира
    		floor = createfloor();
    		wall = createwall(100, 170);
    		wall = createwall(-60, 170);
    		// создаем мячики снизу. Через цикл пробовал, не работает
    		verticals = createverticals(5, 50);
    		verticals = createverticals(10, 50);
    		verticals = createverticals(15, 50);
    		verticals = createverticals(20, 50);
    		verticals = createverticals(25, 50);
    		verticals = createverticals(30, 50);
    		verticals = createverticals(35, 50);
    		verticals = createverticals(5, 55);
    		verticals = createverticals(10, 55);
    		verticals = createverticals(15, 55);
    		verticals = createverticals(20, 55);
    		verticals = createverticals(25, 55);
    		verticals = createverticals(30, 55);
    		verticals = createverticals(35, 55);
    		verticals = createverticals(5, 60);
    		verticals = createverticals(10, 60);
    		verticals = createverticals(15, 60);
    		verticals = createverticals(20, 60);
    		verticals = createverticals(25, 60);
    		verticals = createverticals(30, 60);
    		verticals = createverticals(35, 60);
    		verticals = createverticals(5, 70);
    		verticals = createverticals(10, 70);
    		verticals = createverticals(15, 70);
    		verticals = createverticals(20, 70);
    		verticals = createverticals(25, 70);
    		verticals = createverticals(30, 70);
    		verticals = createverticals(35, 70);
    		verticals = createverticals(5, 80);
    		verticals = createverticals(10, 80);
    		verticals = createverticals(15, 80);
    		verticals = createverticals(20, 80);
    		verticals = createverticals(25, 80);
    		verticals = createverticals(30, 80);
    		verticals = createverticals(35, 80);
    	}
    	public void render() {
    		update(Gdx.graphics.getDeltaTime());
    		Gdx.gl.glClearColor(0, 0, 0, 1);
    		Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
    		b2dr.render(world, camera.combined.scl(Constants.PPM));
    	}
    	public void resize(int width, int height) {
    		camera.setToOrtho(false, width / 2, height / 2);
    	}
    	public void dispose() {
    		world.dispose();
    		b2dr.dispose();
    	}
    	public void update(float delta) {
    		world.step(1 / 60f, 6, 2);
    		inputUpdate(delta);
    		cameraUpdate(delta);
    	}
    	// чтобы мяч вращался
    	public void inputUpdate(float delta) {
    		ball.setAngularVelocity(3.0f);
    	}
    	public void cameraUpdate(float delta) {
    		Vector3 position = camera.position;
    		position.x = ball.getPosition().x * Constants.PPM;
    		position.y = ball.getPosition().y * Constants.PPM;
    		camera.position.set(position);
    		camera.update();
    	}
    	// создаем мячик
    	public Body createPlayer() {
    		Body pBody;
    		BodyDef def = new BodyDef();
    		def.type = BodyDef.BodyType.DynamicBody;
    		def.position.set(20 / Constants.PPM, 800 / Constants.PPM);
    		def.fixedRotation = false;
    		pBody = world.createBody(def);
    		CircleShape shape = new CircleShape();
    		shape.setRadius(10 / Constants.PPM);
    		pBody.createFixture(shape, 1.0f);
    		def.bullet = true;
    		shape.dispose();
    		return pBody;
    	}
    	// создаем пол
    	public Body createfloor() {
    		Body fBody;
    		BodyDef def = new BodyDef();
    		def.type = BodyDef.BodyType.StaticBody;
    		def.position.set(0, 0);
    		def.fixedRotation = true;
    		fBody = world.createBody(def);
    		PolygonShape shape = new PolygonShape();
    		shape.setAsBox(480 / Constants.PPM, 70 / Constants.PPM);
    		fBody.createFixture(shape, 0.001f);
    		shape.dispose();
    		return fBody;
    	}
    	// создаем стены
    	public Body createwall(int xo, int yo) {
    		Body fBody;
    		BodyDef def = new BodyDef();
    		def.type = BodyDef.BodyType.StaticBody;
    		def.position.set(xo / Constants.PPM, yo / Constants.PPM);
    		def.fixedRotation = true;
    		fBody = world.createBody(def);
    		PolygonShape shape = new PolygonShape();
    		shape.setAsBox(50 / Constants.PPM, 100 / Constants.PPM);
    		fBody.createFixture(shape, 0.001f);
    		shape.dispose();
    		return fBody;
    	}
    	// обратите здесь внимание на параметры
    	public Body createverticals(int xo, int yo) {
    		Body pBody;
    		BodyDef def = new BodyDef();
    		def.type = BodyDef.BodyType.DynamicBody;
    		def.position.set(xo / Constants.PPM, yo / Constants.PPM);
    		def.fixedRotation = false;
    		pBody = world.createBody(def);
    		CircleShape shape = new CircleShape();
    		shape.setRadius(2 / Constants.PPM);
    		// здесь заключена вся магия
    		FixtureDef fd = new FixtureDef();
    		// упругость
    		fd.restitution = 1.0f;
    		// плотность
    		fd.density = 5.0f;
    		// трение
    		fd.friction = 0.01f;
    		fd.shape = shape;
    		pBody.createFixture(fd);
    		def.bullet = true;
    		shape.dispose();
    		return pBody;
    	}
    }
    


    Creating a cart in Box2D is not easy. It is necessary to bind the bodies so that they move as a whole. The following GIF only shows the essence.

    image


    How did it happen?
    package com.mygdx.game;
    import com.badlogic.gdx.ApplicationAdapter;
    import com.badlogic.gdx.Gdx;
    import com.badlogic.gdx.Input;
    import com.badlogic.gdx.graphics.GL20;
    import com.badlogic.gdx.graphics.OrthographicCamera;
    import com.badlogic.gdx.graphics.Texture;
    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.Box2DDebugRenderer;
    import com.badlogic.gdx.physics.box2d.CircleShape;
    import com.badlogic.gdx.physics.box2d.PolygonShape;
    import com.badlogic.gdx.physics.box2d.World;
    import utils.Constants;
    public class MyGdxGame extends ApplicationAdapter {
    	SpriteBatch batch;
    	Texture img;
    	private OrthographicCamera camera;
    	private boolean DEBUG = false;
    	private World world;
    	private Body ball;
    	private Body ball1;
    	private Body floor;
    	private Body wall;
    	private Body verticals;
    	private Body horizontals;
    	private Box2DDebugRenderer b2dr;
    	public void create() {
    		float w = Gdx.graphics.getWidth();
    		float h = Gdx.graphics.getHeight();
    		camera = new OrthographicCamera();
    		camera.setToOrtho(false, w / 2, h / 2);
    		world = new World(new Vector2(0, -9.8f), false);
    		b2dr = new Box2DDebugRenderer();
    		// создаем колеса
    		ball = createPlayer(20 / Constants.PPM, 70 / Constants.PPM);
    		ball1 = createPlayer(50 / Constants.PPM, 70 / Constants.PPM);
    		floor = createfloor();
    		wall = createwall(430, 170);
    		wall = createwall(-430, 170);
    		verticals = createverticals();
    	}
    	public void render() {
    		update(Gdx.graphics.getDeltaTime());
    		Gdx.gl.glClearColor(0, 0, 0, 1);
    		Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
    		b2dr.render(world, camera.combined.scl(Constants.PPM));
    	}
    	public void resize(int width, int height) {
    		camera.setToOrtho(false, width / 2, height / 2);
    	}
    	public void dispose() {
    		world.dispose();
    		b2dr.dispose();
    	}
    	public void update(float delta) {
    		world.step(1 / 60f, 6, 2);
    		inputUpdate(delta);
    		cameraUpdate(delta);
    	}
    	public void inputUpdate(float delta) {
    		// задаем вращение колесам. А верхняя планка пусть двигается вместе с ними
    		ball.setLinearVelocity(3.0f, ball.getLinearVelocity().y);
    		ball1.setLinearVelocity(3.0f, ball.getLinearVelocity().y);
    		verticals.setLinearVelocity(3.0f, verticals.getLinearVelocity().y);
    	}
    	public void cameraUpdate(float delta) {
    		Vector3 position = camera.position;
    		position.x = ball.getPosition().x * Constants.PPM;
    		position.y = ball.getPosition().y * Constants.PPM;
    		camera.position.set(position);
    		camera.update();
    	}
    	// два колеса
    	public Body createPlayer(float xo, float yo) {
    		Body pBody;
    		BodyDef def = new BodyDef();
    		def.type = BodyDef.BodyType.DynamicBody;
    		def.position.set(xo, yo);
    		def.fixedRotation = false;
    		pBody = world.createBody(def);
    		CircleShape shape = new CircleShape();
    		shape.setRadius(10 / Constants.PPM);
    		pBody.createFixture(shape, 1.0f);
    		def.bullet = true;
    		shape.dispose();
    		return pBody;
    	}
    	public Body createfloor() {
    		Body fBody;
    		BodyDef def = new BodyDef();
    		def.type = BodyDef.BodyType.StaticBody;
    		def.position.set(0, 0);
    		def.fixedRotation = true;
    		fBody = world.createBody(def);
    		PolygonShape shape = new PolygonShape();
    		shape.setAsBox(480 / Constants.PPM, 70 / Constants.PPM);
    		fBody.createFixture(shape, 0.001f);
    		shape.dispose();
    		return fBody;
    	}
    	public Body createwall(int xo, int yo) {
    		Body fBody;
    		BodyDef def = new BodyDef();
    		def.type = BodyDef.BodyType.StaticBody;
    		def.position.set(xo / Constants.PPM, yo / Constants.PPM);
    		def.fixedRotation = true;
    		fBody = world.createBody(def);
    		PolygonShape shape = new PolygonShape();
    		shape.setAsBox(50 / Constants.PPM, 100 / Constants.PPM);
    		fBody.createFixture(shape, 0.001f);
    		shape.dispose();
    		return fBody;
    	}
    	// вертикальная планка
    	public Body createverticals() {
    		Body fBody;
    		BodyDef def = new BodyDef();
    		def.type = BodyDef.BodyType.DynamicBody;
    		def.position.set(30 / Constants.PPM, 90 / Constants.PPM);
    		def.fixedRotation = true;
    		fBody = world.createBody(def);
    		PolygonShape shape = new PolygonShape();
    		shape.setAsBox(30 / Constants.PPM, 3 / Constants.PPM);
    		fBody.createFixture(shape, 0.001f);
    		shape.dispose();
    		return fBody;
    	}
    }
    


    If you look at the code, you will notice that this is not a real cart, but rather a stick on wheels. Go enthusiasts! There is a video on Youtube where a four-stroke ICE was made in Box2D. Are we worse? Waiting in the comments for your success!

    image


    More clashes!
    package com.mygdx.game;
    import com.badlogic.gdx.ApplicationAdapter;
    import com.badlogic.gdx.Gdx;
    import com.badlogic.gdx.graphics.GL20;
    import com.badlogic.gdx.graphics.OrthographicCamera;
    import com.badlogic.gdx.graphics.Texture;
    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.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 utils.Constants;
    public class MyGdxGame extends ApplicationAdapter {
    	SpriteBatch batch;
    	Texture img;
    	private OrthographicCamera camera;
    	private boolean DEBUG = false;
    	private World world;
    	private Body ball;
    	private Body ball1;
    	private Body ball2;
    	private Body ball3;
    	private Body ball4;
    	private Body ball5;
    	private Body floor;
    	private Body wall;
    	private Body verticals;
    	private Body horizontals;
    	private Box2DDebugRenderer b2dr;
    	public void create() {
    		float w = Gdx.graphics.getWidth();
    		float h = Gdx.graphics.getHeight();
    		camera = new OrthographicCamera();
    		camera.setToOrtho(false, w / 2, h / 2);
    		world = new World(new Vector2(0, -9.8f), false);
    		b2dr = new Box2DDebugRenderer();
    		// создадим шесть больших упругих мячиков
    		ball = createPlayer(20 / Constants.PPM, 150 / Constants.PPM);
    		ball1 = createPlayer(35 / Constants.PPM, 200 / Constants.PPM);
    		ball2 = createPlayer(35 / Constants.PPM, 300 / Constants.PPM);
    		ball3 = createPlayer(20 / Constants.PPM, 400 / Constants.PPM);
    		ball4 = createPlayer(35 / Constants.PPM, 200 / Constants.PPM);
    		ball5 = createPlayer(45 / Constants.PPM, 500 / Constants.PPM);
    		floor = createfloor();
    		wall = createwall(100, 170);
    		wall = createwall(-60, 170);
    	}
    	public void render() {
    		update(Gdx.graphics.getDeltaTime());
    		Gdx.gl.glClearColor(0, 0, 0, 1);
    		Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
    		b2dr.render(world, camera.combined.scl(Constants.PPM));
    	}
    	public void resize(int width, int height) {
    		camera.setToOrtho(false, width / 2, height / 2);
    	}
    	public void dispose() {
    		world.dispose();
    		b2dr.dispose();
    	}
    	public void update(float delta) {
    		world.step(1 / 60f, 6, 2);
    		cameraUpdate(delta);
    	}
    	public void cameraUpdate(float delta) {
    		Vector3 position = camera.position;
    		position.x = ball.getPosition().x * Constants.PPM;
    		position.y = ball.getPosition().y * Constants.PPM;
    		camera.position.set(position);
    		camera.update();
    	}
    	public Body createPlayer(float xo, float yo) {
    		Body pBody;
    		BodyDef def = new BodyDef();
    		def.type = BodyDef.BodyType.DynamicBody;
    		def.position.set(xo, yo);
    		def.fixedRotation = false;
    		pBody = world.createBody(def);
    		CircleShape shape = new CircleShape();
    		shape.setRadius(10 / Constants.PPM);
    		pBody.createFixture(shape, 0.0001f);
    		def.bullet = true;
    		// параметры, благодаря которым они такие упругие
    		FixtureDef fd = new FixtureDef();
    		fd.restitution = 1.0f;
    		fd.density = 5.0f;
    		fd.friction = 0.01f;
    		fd.shape = shape;
    		pBody.createFixture(fd);
    		shape.dispose();
    		return pBody;
    	}
    	public Body createfloor() {
    		Body fBody;
    		BodyDef def = new BodyDef();
    		def.type = BodyDef.BodyType.StaticBody;
    		def.position.set(0, 0);
    		def.fixedRotation = true;
    		fBody = world.createBody(def);
    		PolygonShape shape = new PolygonShape();
    		shape.setAsBox(480 / Constants.PPM, 70 / Constants.PPM);
    		fBody.createFixture(shape, 0.001f);
    		shape.dispose();
    		return fBody;
    	}
    	public Body createwall(int xo, int yo) {
    		Body fBody;
    		BodyDef def = new BodyDef();
    		def.type = BodyDef.BodyType.StaticBody;
    		def.position.set(xo / Constants.PPM, yo / Constants.PPM);
    		def.fixedRotation = true;
    		fBody = world.createBody(def);
    		PolygonShape shape = new PolygonShape();
    		shape.setAsBox(50 / Constants.PPM, 100 / Constants.PPM);
    		fBody.createFixture(shape, 0.001f);
    		shape.dispose();
    		return fBody;
    	}
    }
    


    And the last GIF for today. The inclined plane is familiar to us from the lessons of physics. This code describes how you can get a more complex form (theoretically arbitrary), so that limitless possibilities for gaming physics open up.

    image

    Inclined plane
    public class MyGdxGame extends ApplicationAdapter {
    	SpriteBatch batch;
    	Texture img;
    	private OrthographicCamera camera;
    	private boolean DEBUG = false;
    	private World world;
    	private Body ball;
    	private Body floor;
    	private Body wall;
    	private Body plos;
    	private Body verticals;
    	private Body horizontals;
    	private Box2DDebugRenderer b2dr;
    	public void create() {
    		float w = Gdx.graphics.getWidth();
    		float h = Gdx.graphics.getHeight();
    		camera = new OrthographicCamera();
    		camera.setToOrtho(false, w / 2, h / 2);
    		world = new World(new Vector2(0, -9.8f), false);
    		b2dr = new Box2DDebugRenderer();
    		ball = createPlayer();
    		floor = createfloor();
    		wall = createwall(430, 170);
    		wall = createwall(-430, 170);
    		plos = createplos();
    	}
    	public void render() {
    		update(Gdx.graphics.getDeltaTime());
    		Gdx.gl.glClearColor(0, 0, 0, 1);
    		Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
    		b2dr.render(world, camera.combined.scl(Constants.PPM));
    	}
    	public void resize(int width, int height) {
    		camera.setToOrtho(false, width / 2, height / 2);
    	}
    	public void dispose() {
    		world.dispose();
    		b2dr.dispose();
    	}
    	public void update(float delta) {
    		world.step(1 / 60f, 6, 2);
    		cameraUpdate(delta);
    	}
    	public void cameraUpdate(float delta) {
    		Vector3 position = camera.position;
    		position.x = ball.getPosition().x * Constants.PPM;
    		position.y = ball.getPosition().y * Constants.PPM;
    		camera.position.set(position);
    		camera.update();
    	}
    	public Body createPlayer() {
    		Body pBody;
    		BodyDef def = new BodyDef();
    		def.type = BodyDef.BodyType.DynamicBody;
    		def.position.set(30 / Constants.PPM, 190 / Constants.PPM);
    		def.fixedRotation = false;
    		pBody = world.createBody(def);
    		CircleShape shape = new CircleShape();
    		shape.setRadius(10 / Constants.PPM);
    		pBody.createFixture(shape, 1.0f);		
    		def.bullet = true;
    		shape.dispose();
    		return pBody;
    	}
    	public Body createfloor() {
    		Body fBody;
    		BodyDef def = new BodyDef();
    		def.type = BodyDef.BodyType.StaticBody;
    		def.position.set(0, 0);
    		def.fixedRotation = true;
    		fBody = world.createBody(def);
    		PolygonShape shape = new PolygonShape();
    		shape.setAsBox(480 / Constants.PPM, 70 / Constants.PPM);
    		fBody.createFixture(shape, 0.001f);
    		shape.dispose();
    		return fBody;
    	}
    	public Body createwall(int xo, int yo) {
    		Body fBody;
    		BodyDef def = new BodyDef();
    		def.type = BodyDef.BodyType.StaticBody;
    		def.position.set(xo / Constants.PPM, yo / Constants.PPM);
    		def.fixedRotation = true;
    		fBody = world.createBody(def);
    		PolygonShape shape = new PolygonShape();
    		shape.setAsBox(50 / Constants.PPM, 100 / Constants.PPM);
    		fBody.createFixture(shape, 0.001f);
    		shape.dispose();
    		return fBody;
    	}
    	public Body createplos() {
    		Vector2[] vertices = new Vector2[3];
    	    vertices[0] = new Vector2(0f  , -0.6f  );
    	    vertices[1] = new Vector2(1f , -0.6f  );
    	    vertices[2] = new Vector2(1f , 1f);
    	    PolygonShape shape = new PolygonShape();
    		Body fBody;
    		BodyDef def = new BodyDef();
    		def.type = BodyDef.BodyType.StaticBody;
    		def.position.set(20 / Constants.PPM, 90 / Constants.PPM);
    		def.fixedRotation = true;
    		fBody = world.createBody(def);
    		shape.set(vertices);
    		fBody.createFixture(shape, 0.001f);
    		shape.dispose();
    		return fBody;
    	}
    }
    


    I hope that thanks to this code you will be able to understand the basics of Box2D, and extremely excellent applications will be born! Thank you for reading to the end! I will try to answer all the questions in the comments!

    Also popular now: