9

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

4

2 回答 2

16

这是 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);
    }
}
于 2013-03-16T21:19:23.990 回答
4

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

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

于 2013-03-16T21:24:00.320 回答