مساء الخير ، عزيزي القارئ! أنا ، مبرمج جافا للمبتدئين ، لم أستطع التعود على مكتبة Box2D لفترة طويلة. أولاً ، نظرًا لحقيقة أنه تمت كتابته من أجل C ++ ، وليس هناك وثائق لذلك ، ولا أعرف بناء جملة C. ثانياً ، نظرًا لحقيقة أن الدروس المفصلة في هذه المكتبة متاحة فقط كامتداد لـ libGDX. بعد أسبوعين من الصراع الصعب ، تمكنت أخيرًا من فهم كيفية العمل مع هذه المكتبة ، وفي هذا المقال سأتحدث عنها (وأظهرها).
أنا أعمل في
Eclipse ، سيتم ربط المقالة مع بيئة التطوير هذه. للبدء ، قم بتنزيل
أداة تجميع
libGDX وقم بإنشاء بنية قياسية. نحن بحاجة إلى تطبيق سطح المكتب مع تمديد Box2D. ثم انتقل إلى Eclipse ، انقر فوق ملف → استيراد → Gradle → Gradle Project وحدد المسار إلى التجميع الخاص بك.
هنا صورة توضح كيف يبدو لي. أضفت حزمة Utils مع فئة الثوابت إلى المجلد Core ، والذي يحتوي على ثابت واحد فقط - عدد البكسل لكل متر. هذا هو أن العالم ليس عملاقا.
فيما يلي رمز فئة 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();
سيكون هناك الكثير من التعليمات البرمجية ، لذلك سوف أرفقها في المفسدين. يتم تغيير فئة MyGdxGame فقط من حزمة com.mygdx.game.
لذلك ، دعونا نحاول القيام بشيء بسيط إلى حد ما في طلبنا. مسار الكرة يصطدم بالجدار من الألواح ، وينتشر. شيء مثل هذا:

فكرة 1. البولينج 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;
اتضح عظيم ، أليس كذلك؟ من خلال تغيير العديد من المعلمات ، يمكنك تحقيق ما تحتاجه بالضبط! ولا تكتب الكثير من أسطر التعليمات البرمجية.
ولكن الآن أريد أن أرى ضربة مرنة. ودع هناك المزيد من الأشياء على المسرح. نحصل على النتيجة التالية:

وهنا هو الكود: 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();
إنشاء عربة في Box2D ليس بالأمر السهل. من الضروري ربط الهيئات بحيث تتحرك ككل. يظهر GIF التالي فقط الجوهر.

كيف حدث هذا؟ 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();
إذا نظرت إلى الكود ، ستلاحظ أن هذه ليست عربة حقيقية ، بل هي عصا على العجلات. الذهاب المتحمسين! يوجد
مقطع فيديو على Youtube حيث تم تصنيع ICE رباعي الأشواط في 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();
وآخر GIF لهذا اليوم. الطائرة المائلة مألوفة بالنسبة لنا من دروس الفيزياء. يصف هذا الرمز كيف يمكنك الحصول على نموذج أكثر تعقيدًا (تعسفيًا نظريًا) ، بحيث تفتح إمكانيات غير محدودة لفيزياء الألعاب.

طائرة مائلة 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 ، وسيتم إنشاء تطبيقات ممتازة للغاية! شكرا لك على القراءة حتى النهاية! سأحاول الإجابة على جميع الأسئلة الواردة في التعليقات!