Добрый день, уважаемый читатель! Я, начинающий Java-программист, долгое время не мог освоиться с библиотекой Box2D. Во-первых, из-за того, что она написана для C++, и по ней нет документации, а синтаксис Си я не знаю. Во-вторых, из-за того, что подробные уроки по этой библиотеке есть только в качестве расширения libGDX. Спустя пару недель упорной борьбы, я наконец смог понять, как надо работать с этой библиотекой, и в этой статье я расскажу об этом (и покажу это).
Работаю в Eclipse, статья будет связана с этой средой разработки. Для начала скачайте сборщик libGDX и сделайте стандартную сборку. Нам понадобится Desktop’ное приложение с расширением Box2D. Потом заходите в Eclipse, нажимаете File → Import → Gradle → Gradle Project и указываете путь к вашей сборке.
Вот изображение с демонстрацией того, как выглядит моя. Я добавил в папку Core пакет Utils с классом Constants, в котором содержится только одна константа – к-во пикселей в метре. Это для того, чтобы мир не был гигантским.
Вот код для класса DesktopLauncher из пакета com.mygdx.game.desktop:
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);
}
}
Кода будет много, поэтому я заключу его в спойлеры. Изменяется только класс MyGdxGame из пакета com.mygdx.game.
Итак, попробуем сделать довольно простую вещь в нашем приложении. Путь мячик врезается в стену из дощечек, и они разлетаются. Что-то подобное:
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;
}
}
Замечательно получилось, не так ли? Изменив несколько параметров, вы можете добиться именно того, что нужно вам! И не надо писать так много строк кода.
Но теперь хочется увидеть упругий удар. И пусть объектов на сцене будет побольше. Получим такой результат:
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;
}
}
Создать тележку в Box2D непросто. Нужно связывать тела, чтобы они двигались, как единое целое. Следующая гифка демонстрирует только суть.
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;
}
}
Если вы присмотритесь к коду, то заметите, что это не настоящая тележка, а, скорее, палочка на колесиках. Вперед, энтузиасты! На Youtube есть видео, где в Box2D сделали четырехтактный ДВС. Разве мы хуже? Жду в комментариях Ваши успехи!
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;
}
}
И последняя гифка на сегодня. Наклонная плоскость знакома нам с уроков физики. В данном коде представлено, как можно получить более сложную форму (теоретически произвольную), чтобы открылись безграничные возможности для игровой физики.
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;
}
}
Надеюсь, благодаря этому коду Вам удастся разобраться с основами Box2D, и на свет появятся исключительно превосходные приложения! Спасибо, что прочли до конца! Постараюсь ответить на все вопросы в комментариях!
Автор: Васильев Алексей