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.
Here is the code for the DesktopLauncher class from com.mygdx.game.desktop:
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:
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:
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.
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!
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.
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!
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.
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:
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:
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.
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!
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.
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!