【问题标题】:how to use the libgdx contactlistener如何使用 libgdx 联系人监听器
【发布时间】:2013-03-05 09:26:45
【问题描述】:

我刚刚开始使用 Libgdx 的 Box2d 引擎,但我根本不明白什么时候应该调用 Contactlistener 的方法。一方面是“开始接触”,另一方面是“结束接触”。我应该在哪里打电话给他们,以获得某个固定装置的数量接触其他人?以及如何实现 Contactlistener? 重定向到教程将回答我的问题。我在谷歌搜索时没有找到任何东西。 这个one 对我帮助很大,但它是为 C++ 编写的,并不涉及到主游戏圈的实现。 谢谢你帮助我;)

【问题讨论】:

    标签: java box2d libgdx contact game-physics


    【解决方案1】:

    这是 libgdx 的一个简短示例。它展示了如何创建一个 ContactListener 以显示在建立和断开联系时涉及哪些固定装置。它还显示了 world.getContactList() 的使用,它将返回物理步骤之后仍然存在的联系人列表。这可能会错过在物理步骤过程中建立和断开的联系。如果您对这些感兴趣,那么您将想要实现一个 ContactListener,使用 beginContact() 来检测何时建立联系并使用 endContact()检测它们何时损坏。

    package hacks;
    
    import com.badlogic.gdx.Gdx;
    import com.badlogic.gdx.backends.lwjgl.LwjglApplication;
    import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration;
    import com.badlogic.gdx.graphics.GL10;
    import com.badlogic.gdx.graphics.OrthographicCamera;
    import com.badlogic.gdx.math.MathUtils;
    import com.badlogic.gdx.math.Vector2;
    import com.badlogic.gdx.physics.box2d.Body;
    import com.badlogic.gdx.physics.box2d.BodyDef;
    import com.badlogic.gdx.physics.box2d.BodyDef.BodyType;
    import com.badlogic.gdx.physics.box2d.Box2DDebugRenderer;
    import com.badlogic.gdx.physics.box2d.Contact;
    import com.badlogic.gdx.physics.box2d.ContactImpulse;
    import com.badlogic.gdx.physics.box2d.ContactListener;
    import com.badlogic.gdx.physics.box2d.Fixture;
    import com.badlogic.gdx.physics.box2d.FixtureDef;
    import com.badlogic.gdx.physics.box2d.Manifold;
    import com.badlogic.gdx.physics.box2d.PolygonShape;
    import com.badlogic.gdx.physics.box2d.World;
    
    public class Box2DDemoMain extends com.badlogic.gdx.Game {
    
        private static final float SCALING = 0.1f;
    
        private Box2DDebugRenderer debugRenderer;
        private OrthographicCamera camera;
        private World world;
    
        @Override
        public void create() {
            debugRenderer = new Box2DDebugRenderer();
            camera = new OrthographicCamera();
    
            createWorld();
            createCollisionListener();
            createGround();
            createBox();
        }
    
        private void createWorld() {
            Vector2 gravity = new Vector2(0, -10);
            world = new World(gravity, true);
        }
    
        private void createCollisionListener() {
            world.setContactListener(new ContactListener() {
    
                @Override
                public void beginContact(Contact contact) {
                    Fixture fixtureA = contact.getFixtureA();
                    Fixture fixtureB = contact.getFixtureB();
                    Gdx.app.log("beginContact", "between " + fixtureA.toString() + " and " + fixtureB.toString());
                }
    
                @Override
                public void endContact(Contact contact) {
                    Fixture fixtureA = contact.getFixtureA();
                    Fixture fixtureB = contact.getFixtureB();
                    Gdx.app.log("endContact", "between " + fixtureA.toString() + " and " + fixtureB.toString());
                }
    
                @Override
                public void preSolve(Contact contact, Manifold oldManifold) {
                }
    
                @Override
                public void postSolve(Contact contact, ContactImpulse impulse) {
                }
    
            });
        }
    
        private void createGround() {
            PolygonShape groundShape = new PolygonShape();
            groundShape.setAsBox(50, 1);
            BodyDef groundBodyDef = new BodyDef();
            groundBodyDef.type = BodyType.StaticBody;
            groundBodyDef.position.set(0, -20);
            Body groundBody = world.createBody(groundBodyDef);
            FixtureDef fixtureDef = new FixtureDef();
            fixtureDef.shape = groundShape;
            groundBody.createFixture(fixtureDef);
            groundShape.dispose();
        }
    
        private void createBox() {
            PolygonShape boxShape = new PolygonShape();
            boxShape.setAsBox(1, 1);
            BodyDef boxBodyDef = new BodyDef();
            boxBodyDef.position.set(0, 20);
            boxBodyDef.angle = MathUtils.PI / 32;
            boxBodyDef.type = BodyType.DynamicBody;
            boxBodyDef.fixedRotation = false;
            Body boxBody = world.createBody(boxBodyDef);
            FixtureDef boxFixtureDef = new FixtureDef();
            boxFixtureDef.shape = boxShape;
            boxFixtureDef.restitution = 0.75f;
            boxFixtureDef.density = 2.0f;
            boxBody.createFixture(boxFixtureDef);
            boxShape.dispose();
        }
    
        @Override
        public void resize(int width, int height) {
            super.resize(width, height);
            float cameraWidth = Gdx.graphics.getWidth() * SCALING;
            float cameraHeight = Gdx.graphics.getHeight() * SCALING;
            camera.setToOrtho(false, cameraWidth, cameraHeight);
            camera.position.set(0, 0, 0);
        }
    
        @Override
        public void render() {
            super.render();
    
            world.step(Gdx.graphics.getDeltaTime(), 8, 3);
    
            int numContacts = world.getContactCount();
            if (numContacts > 0) {
                Gdx.app.log("contact", "start of contact list");
                for (Contact contact : world.getContactList()) {
                    Fixture fixtureA = contact.getFixtureA();
                    Fixture fixtureB = contact.getFixtureB();
                    Gdx.app.log("contact", "between " + fixtureA.toString() + " and " + fixtureB.toString());
                }
                Gdx.app.log("contact", "end of contact list");
            }
    
            Gdx.gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
            Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
            camera.update();
            debugRenderer.render(world, camera.combined);
        }
    
        public static void main(String[] args) {
            LwjglApplicationConfiguration config = new LwjglApplicationConfiguration();
    
            config.title = Box2DDemoMain.class.getName();
            config.width = 800;
            config.height = 480;
            config.fullscreen = false;
            config.useGL20 = true;
            config.useCPUSynch = true;
            config.forceExit = true;
            config.vSyncEnabled = true;
    
            new LwjglApplication(new Box2DDemoMain(), config);
        }
    }
    

    【讨论】:

    • 这一行中的 8 和 3 是什么意思? world.step(Gdx.graphics.getDeltaTime(), 8, 3);
    • 它们分别是速度迭代和位置迭代。这些值是 Box2D 手册推荐的。请参阅第 2.4 节 - 手册在这里:box2d.org/manual.html
    【解决方案2】:

    您不必在任何地方调用这些方法。只需创建一个类并在其中实现 ContactListener 。现在在您的代码中只需使用 world.setContactListener(ContactListener listener) 。

    当你的世界发生碰撞时,所有 4 个方法都会被调用。您将获得 2 个碰撞体的fixtureA 和fixtureB

    【讨论】:

    • 没有办法只听身体的接触吗?喜欢body.setContactListener(new ContactListenger{...})。这样我只需要检查 other 碰撞对象是什么,并且始终确定第一个是 body 对象。在world.setContactListener 时,我总是要先检查两个夹具主体。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-20
    • 2010-11-26
    • 2021-05-29
    相关资源
    最近更新 更多