рдкреЗрд░реАрдкреБрддрдо рдореЛрдмрд╛рдЗрд▓

рд╢реБрдн рджреЛрдкрд╣рд░, рдкреНрд░рд┐рдп рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ habr.com! рдпрд╣ рдЗрд╕ рд╡рд┐рд╖рдп рдкрд░ рддреАрд╕рд░рд╛ рд▓реЗрдЦ рд╣реИред рдореИрдВ рджрд┐рди рднрд░ рдХрд╛рдо рдХрд░рддрд╛ рд╣реВрдВ, рдореИрдВ рдЦреБрдж рдХреЛ рдЕрджреНрднреБрдд Box2D рд▓рд╛рдЗрдмреНрд░реЗрд░реА рд╕реЗ рджреВрд░ рдирд╣реАрдВ рдХрд░ рд╕рдХрддрд╛ред

рдпрджрд┐ рдЖрдкрдиреЗ рдкрд╣рд▓реЗ рдФрд░ рджреВрд╕рд░реЗ рд▓реЗрдЦ рдХреЛ рдирд╣реАрдВ рдкрдврд╝рд╛ рд╣реИ, рддреЛ рдЕрд╡рд╢реНрдп рджреЗрдЦреЗрдВ, рдпрд╣ рдордЬреЗрджрд╛рд░ рд╣реЛрдЧрд╛! рдореИрдВ рдЧреНрд░рд╣рдг рдореЗрдВ рдХрд╛рдо рдХрд░рддрд╛ рд╣реВрдВ, рдореИрдВ рдЬрд╛рд╡рд╛ рдореЗрдВ рд▓рд┐рдЦрддрд╛ рд╣реВрдВред рдореИрдВрдиреЗ рдЕрдкрдиреЗ рд▓реЗрдЦ рдХреЛ рдРрд╕рд╛ рдХреНрдпреЛрдВ рдХрд╣рд╛? рдЖрдЧреЗ рдкрдврд╝реЗрдВ - рдФрд░ рдмрд╣реБрдд рдЬрд▓реНрдж рд╕рдм рдХреБрдЫ рд╕реНрдкрд╖реНрдЯ рд╣реЛ рдЬрд╛рдПрдЧрд╛! Spoiler: рд╣рдо рдЕрдкрдиреА рд╕реНрд╡рдпрдВ рдХреА рд╕реНрдерд╛рдпреА рдЧрддрд┐ рдорд╢реАрди (рдХрд╛рд░реЛрдВ рдХреЗ рд▓рд┐рдП рд╕рд╣рд┐рдд) рдмрдирд╛рдПрдВрдЧреЗ, рдФрд░, рд╢рд╛рдпрдж, рд╣рдо рдорд╢реАрди рдЦреБрдж рдмрдирд╛рдПрдВрдЧреЗ!

рдЫрд╡рд┐

рдЪрд┐рддреНрд░рд╛ 1. рд╕рджрд╛ рдЧрддрд┐ рдорд╢реАрдиред

рддреЛ, рдЖрдЬ рд╣рдо рдХреБрдЫ рдРрд╕рд╛ рдкрд╛рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реЗрдВрдЧреЗ:

рдЫрд╡рд┐

рдЪрд┐рддреНрд░рд╛ 2. рдЗрдВрдЬрди рдХреЗ рд╕рд╛рде рдорд╢реАрдиред

рд╣рд╛рдБ, рдпрд╣ рдПрдХ рдЯрд╛рдЗрдкреЛ рдирд╣реАрдВ рд╣реИ! рдЖрдЬ рд╣рдо рдПрдХ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдЗрдВрдЬрди рдХреЗ рд╕рд╛рде рдПрдХ рдорд╢реАрди рдмрдирд╛рдПрдВрдЧреЗ, рдпрд╣ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рд╕реЗ рдЕрдкреНрд░рднреЗрджреНрдп рд╣реЛрдЧрд╛! рдпрд╣ рдкрд╣рд▓реЗ рд▓реЗрдЦ рд╕реЗ рдЖрдкрдХреЗ рд▓рд┐рдП "рдЧрд╛рдбрд╝реА" рдирд╣реАрдВ рд╣реИред

LibGDX рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП , рдкрд╣рд▓рд╛ рд▓реЗрдЦ рджреЗрдЦреЗрдВред

рдпрд╣рд╛рдБ рдПрдХ рдЪрд┐рддреНрд░ рджрд┐рдЦрд╛ рд░рд╣рд╛ рд╣реИ рдХрд┐ рдореЗрд░реА рд╕рднрд╛ рдХреИрд╕реА рджрд┐рдЦрддреА рд╣реИред рдореИрдВрдиреЗ рдХреЛрд░ рдлрд╝реЛрд▓реНрдбрд░ рдореЗрдВ рдХреЙрдиреНрд╕реНрдЯреЗрдВрдЯ рдХреНрд▓рд╛рд╕ рдХреЗ рд╕рд╛рде рдпреВрдЯрд┐рд▓реНрд╕ рдкреИрдХреЗрдЬ рдХреЛ рдЬреЛрдбрд╝рд╛, рдЬрд┐рд╕рдореЗрдВ рдХреЗрд╡рд▓ рдПрдХ рд╕реНрдерд┐рд░ - рдкреНрд░рддрд┐ рдореАрдЯрд░ рдкрд┐рдХреНрд╕рд▓ рдХреА рд╕рдВрдЦреНрдпрд╛ рд╣реИред рдРрд╕рд╛ рдЗрд╕рд▓рд┐рдП рд╣реИ рдХрд┐ рджреБрдирд┐рдпрд╛ рд╡рд┐рд╢рд╛рд▓ рдирд╣реАрдВ рд╣реИред

рдЫрд╡рд┐

рдЪрд┐рддреНрд░рд╛ 3. рдореЗрд░рд╛ рдирд┐рд░реНрдорд╛рдгред

рдпрд╣рд╛рдБ com.mygdx.game.desktop рд╕реЗ DesktopLauncher рд╡рд░реНрдЧ рдХреЗ рд▓рд┐рдП рдХреЛрдб рд╣реИ:

рдЗрд╕ рдХреЛрдб рдХреЛ рдХрдХреНрд╖рд╛ рдореЗрдВ рдкреЗрд╕реНрдЯ рдХрд░реЗрдВ рдФрд░ рдЗрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рднреВрд▓ рдЬрд╛рдПрдВред
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.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 com.badlogic.gdx.physics.box2d.joints.RevoluteJointDef; import utils.Constants; public class MyGdxGame extends ApplicationAdapter { private OrthographicCamera camera; private boolean DEBUG = false; private World world; private Box2DDebugRenderer b2dr; //  private Body box; //   private Body backweel; //   private Body frontweel; private Body floor; private Body triangle; //   private float m = -20; 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(); //   floor = createFloor(); //   triangle = createTriangle(20f, 40f, 30f, -2f, -2f, 5f); triangle = createTriangle(50f, 60f, 80f, -2f, 10f, -2f); triangle = createTriangle(100f, 160f, 200f, -2f, 20f, -2f); triangle = createTriangle(280f, 290f, 300f, -2f, 100f, -2f); //   box = createBox(); //   backweel = createWeel(-1f, 2f); frontweel = createWeel(4.5f, 2f); //        connected(); } //      public void connected() { revJoint(box, backweel, -1f * 10 / utils.Constants.PPM, -2f * 10 / utils.Constants.PPM); revJoint(box, frontweel, 4.5f * 10 / utils.Constants.PPM, -2f * 10 / utils.Constants.PPM); } //   !  ! public void revJoint(Body body1, Body body2, float xo, float yo) { //   RevoluteJointDef rjd = new RevoluteJointDef(); //    rjd.enableMotor = true; //  .      ,  ,  //  .    .   -   ! rjd.motorSpeed = m; //   rjd.maxMotorTorque = 30; rjd.collideConnected = false; rjd.bodyA = body1; rjd.bodyB = body2; rjd.localAnchorA.set(xo, yo); world.createJoint(rjd); } 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); inputUpdate(delta); } //       ,     public void inputUpdate(float delta) { if (Gdx.input.isKeyPressed(Keys.SPACE)) { box.setLinearVelocity(5, 5); } } //     public void cameraUpdate(float delta) { Vector3 position = camera.position; position.x = box.getPosition().x * Constants.PPM; position.y = box.getPosition().y * Constants.PPM; camera.position.set(position); camera.update(); } //     public Body createBox() { Vector2[] verticles = new Vector2[8]; verticles[0] = new Vector2(2f * 10 / utils.Constants.PPM, 2f * 10 / utils.Constants.PPM); verticles[1] = new Vector2(2f * 10 / utils.Constants.PPM, -2f * 10 / utils.Constants.PPM); verticles[2] = new Vector2(-2f * 10 / utils.Constants.PPM, 2f * 10 / utils.Constants.PPM); verticles[3] = new Vector2(-2f * 10 / utils.Constants.PPM, -2f * 10 / utils.Constants.PPM); verticles[4] = new Vector2(6f * 10 / utils.Constants.PPM, -2f * 10 / utils.Constants.PPM); verticles[5] = new Vector2(6f * 10 / utils.Constants.PPM, 0f * 10 / utils.Constants.PPM); verticles[6] = new Vector2(-1f * 10 / utils.Constants.PPM, -2f * 10 / utils.Constants.PPM); verticles[7] = new Vector2(4.5f * 10 / utils.Constants.PPM, -2f * 10 / utils.Constants.PPM); PolygonShape shape = new PolygonShape(); Body fBody; BodyDef def = new BodyDef(); def.type = BodyDef.BodyType.DynamicBody; def.position.set(0, 0); def.fixedRotation = false; fBody = world.createBody(def); shape.set(verticles); //    FixtureDef fd = new FixtureDef(); // ,     fd.shape = shape; //   fd.friction = 0.5f; //   fd.density = 3f; //   fd.restitution = 0.5f; fBody.createFixture(fd); fBody.createFixture(fd); shape.dispose(); return fBody; } //   public Body createWeel(float xo, float yo) { CircleShape shape = new CircleShape(); Body fBody; BodyDef def = new BodyDef(); def.type = BodyDef.BodyType.DynamicBody; def.position.set(xo * 10 / utils.Constants.PPM, yo * 10 / utils.Constants.PPM); def.fixedRotation = false; fBody = world.createBody(def); shape.setRadius(2.0f * 10 / utils.Constants.PPM); //    FixtureDef fd = new FixtureDef(); fd.shape = shape; fd.friction = 0.7f; fd.density = 3f; fd.restitution = 0.5f; fBody.createFixture(fd); shape.dispose(); return fBody; } //   public Body createFloor() { Vector2[] verticles = new Vector2[4]; verticles[0] = new Vector2(-100f * 10 / utils.Constants.PPM, -2f * 10 / utils.Constants.PPM); verticles[1] = new Vector2(300f * 10 / utils.Constants.PPM, -2f * 10 / utils.Constants.PPM); verticles[2] = new Vector2(300f * 10 / utils.Constants.PPM, -5f * 10 / utils.Constants.PPM); verticles[3] = new Vector2(-100f * 10 / utils.Constants.PPM, -5f * 10 / utils.Constants.PPM); PolygonShape shape = new PolygonShape(); Body fBody; BodyDef def = new BodyDef(); def.type = BodyDef.BodyType.StaticBody; def.position.set(0, 0); def.fixedRotation = true; fBody = world.createBody(def); shape.set(verticles); FixtureDef fd = new FixtureDef(); fd.shape = shape; fd.friction = 0.5f; fd.density = 3f; fd.restitution = 0.5f; fBody.createFixture(fd); shape.dispose(); return fBody; } //    ! public Body createTriangle(float xo, float x1, float x2, float yo, float y1, float y2) { Vector2[] verticles = new Vector2[3]; verticles[0] = new Vector2(xo * 10 / utils.Constants.PPM, yo * 10 / utils.Constants.PPM); verticles[1] = new Vector2(x1 * 10 / utils.Constants.PPM, y1 * 10 / utils.Constants.PPM); verticles[2] = new Vector2(x2 * 10 / utils.Constants.PPM, y2 * 10 / utils.Constants.PPM); PolygonShape shape = new PolygonShape(); Body fBody; BodyDef def = new BodyDef(); def.type = BodyDef.BodyType.StaticBody; def.position.set(0, 0); def.fixedRotation = true; fBody = world.createBody(def); shape.set(verticles); FixtureDef fd = new FixtureDef(); fd.shape = shape; fd.friction = 0.5f; fd.density = 10f; fd.restitution = 0f; fBody.createFixture(fd); shape.dispose(); return fBody; } } 



рдЫрд╡рд┐
рдЪрд┐рддреНрд░ 4. рд╕рдВрдХрд▓рди рдХрд░рддреЗ рд╕рдордп рд╣рдореЗрдВ рдХреНрдпрд╛ рдорд┐рд▓рддрд╛ рд╣реИ?

рд╣рдо рдЕрдкрдиреА рдХрд╛рд░ рдХреЛ рдПрдХ рдореЛрдЯрд░ рдмрдирд╛рддреЗ рд╣реИрдВ рдЬреЛ рдЙрд╕рдХреЗ рдкрд╣рд┐рдпреЗ рдХреЛ рдШреБрдорд╛рддреА рд╣реИред рд▓реЗрдХрд┐рди рдпрд╣ рд╣рдореЗрд╢рд╛ рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдХреЛрдИ рдКрд░реНрдЬрд╛ рдиреБрдХрд╕рд╛рди рдирд╣реАрдВ рд╣реИрдВред рдЗрд╕ рдкреНрд░рдХрд╛рд░ рд╣рдо рдЕрдкрдиреА рд╕реНрдерд╛рдпреА рдЧрддрд┐ рдорд╢реАрди рдмрдирд╛рддреЗ рд╣реИрдВ!

рдФрд░ рдЖрдкрдХреЛ рдЖрд╢реНрдЪрд░реНрдп рд╣реИ рдХрд┐ рд╕реНрддрд░ рдХреЗ рдЕрдВрдд рдореЗрдВ рдХреНрдпрд╛ рд╣реИ? рдЯрд┐рдкреНрдкрдгрд┐рдпреЛрдВ рдореЗрдВ рд╕реНрдХреНрд░реАрдирд╢реЙрдЯ рднреЗрдЬреЗрдВ рдЬреИрд╕реЗ рд╣реА рдЖрдк рдЬрд╛рддреЗ рд╣реИрдВред рд▓реЗрдЦ рдХреЛ рдЕрдВрдд рддрдХ рдкрдврд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж! рдореБрдЭреЗ рдЖрд╢рд╛ рд╣реИ рдХрд┐ рдЖрдк Box2D рдореЗрдВ рдЕрдкрдиреА рдЦреБрдж рдХреА рдХрд╛рд░ рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ!

рдкреБрдирд╢реНрдЪ рдореИрдВ рдЖрдкрдХреЗ рд╕рд╡рд╛рд▓реЛрдВ рдХреЗ рдЬрд╡рд╛рдм рдХреЗ рд▓рд┐рдП рддрддреНрдкрд░ рд╣реВрдВ! рдЧреЗрдорд┐рдВрдЧ рднреМрддрд┐рдХреА рд▓рдВрдмреЗ рд╕рдордп рддрдХ рдЬреАрд╡рд┐рдд рд░рд╣реЗрдВ!

Source: https://habr.com/ru/post/hi450442/


All Articles