java - 如何在碰撞时仅删除数组中的一个 Body? Libgdx

标签 java android libgdx collision-detection

我正在用 Libgdx 编写一个游戏。在我的游戏中,我同时创建了 5 枚火箭(使用数组)和一只鸟(玩家)。我使用 ContactListener 来检测火箭和 Bird 之间的碰撞,如下所示:

if ((BodyUtils.bodyIsBird(a) && BodyUtils.bodyIsBoom(b))
                || (BodyUtils.bodyIsBird(b) && BodyUtils.bodyIsBoom(a))) {
               explosion_sound.play();
               removeRocket();
     }

碰撞时,我只想移除五分之一的火箭,即真正与我的鸟碰撞的火箭。我在removeRocket()中编写了这样的代码,但它删除了所有5个火箭,我不希望这样:

    Array<Body> bodies = new Array<Body>(world.getBodyCount());
    world.getBodies(bodies);
    for (Body body : bodies) {
        if (BodyUtils.bodyIsBoom(body)) {
            world.destroyBody (body);
          }
        }
    }

请帮助我!

最佳答案

使用这个循环:

Array<Body> bodies = new Array<Body>(world.getBodyCount());
    world.getBodies(bodies);
    for (Body body : bodies) {
        if (BodyUtils.bodyIsBoom(body)) {
            world.destroyBody (body);
          }
        }
    }

您迭代世界中的所有物体并删除所有属于火箭的物体(BodyUtils.bodyIsBoom(body) 计算结果为 true)。

你永远不会指定你真正想要摧毁的 body !

只需向您的removeRocket(或removeBody)方法添加一个参数来指定要删除的主体,如下所示:

// In your contact listener
if (BodyUtils.bodyIsBird(a) && BodyUtils.bodyIsBoom(b))
{
    explosion_sound.play();
    removeBody(b);
}
if (BodyUtils.bodyIsBird(b) && BodyUtils.bodyIsBoom(a))
{
    explosion_sound.play();
    removeBody(a);
}

private final Array<Body> toBeRemovedBodies = new Array<Body>();

public void removeBody(Body body)
{
    toBeRemovedBodies.add(body);
}

// After you stepped you world
for(Body body : toBeRemovedBodies)
    world.destroyBody(body);

旁注:如您所见,我不会在removeBody方法中销毁主体,因为它是在世界当前处于模拟状态时调用的,并且在此期间不得销毁主体,因为它可能会导致不可预测的结果行为。

编辑:

由于再次阅读您的问题后,我不确定我是否完全理解它,这就是为什么我创建了一个关于如何在接触时摧毁 body 的小而完整的示例:

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.math.Vector2;
import com.badlogic.gdx.physics.box2d.*;
import com.badlogic.gdx.utils.Array;

public class TestGame extends ApplicationAdapter
{
    enum BodyData
    {
        BIRD, ROCKET;
    }

    class MyContactListener implements ContactListener
    {

        @Override
        public void beginContact(Contact contact)
        {
            Body a = contact.getFixtureA().getBody();
            Body b = contact.getFixtureB().getBody();

            if (a.getUserData() == BodyData.BIRD
                    && b.getUserData() == BodyData.ROCKET)
            {
                // play sound
                toBeDeletedBodies.add(b);
            }
            if (b.getUserData() == BodyData.BIRD
                    && a.getUserData() == BodyData.ROCKET)
            {
                // play sound
                toBeDeletedBodies.add(a);
            }
        }

        @Override
        public void endContact(Contact contact)
        {
            // TODO Auto-generated method stub

        }

        @Override
        public void preSolve(Contact contact, Manifold oldManifold)
        {
            // TODO Auto-generated method stub

        }

        @Override
        public void postSolve(Contact contact, ContactImpulse impulse)
        {
            // TODO Auto-generated method stub

        }

    }

    Array<Body>         toBeDeletedBodies   = new Array<>();
    Array<Body>         allBodies           = new Array<>();

    World               world;

    Box2DDebugRenderer  renderer;

    OrthographicCamera  camera;

    @Override
    public void create()
    {
        world = new World(new Vector2(0, -1), true);

        BodyDef bodyDefBird = new BodyDef();
        bodyDefBird.position.set(0, 0.1f);
        bodyDefBird.type = BodyDef.BodyType.DynamicBody;

        BodyDef bodyDefRocket1 = new BodyDef();
        bodyDefRocket1.position.set(0, 0.5f);
        bodyDefRocket1.type = BodyDef.BodyType.DynamicBody;

        BodyDef bodyDefRocket2 = new BodyDef();
        bodyDefRocket2.position.set(0.1f, 0.8f);
        bodyDefRocket2.type = BodyDef.BodyType.DynamicBody;

        FixtureDef circleFixture = new FixtureDef();
        circleFixture.shape = new CircleShape();
        ((CircleShape) circleFixture.shape).setRadius(0.02f);

        FixtureDef rocketFixture = new FixtureDef();
        rocketFixture.shape = new PolygonShape();
        ((PolygonShape) rocketFixture.shape).set(new float[]
        { 0, 0, 0.01f, 0, 0.01f, 0.05f, 0, 0.05f, 0, 0 });

        BodyDef bodyDefFloor = new BodyDef();
        bodyDefFloor.position.set(-100, 0);
        bodyDefFloor.type = BodyDef.BodyType.StaticBody;

        FixtureDef lineFixture = new FixtureDef();
        lineFixture.shape = new EdgeShape();
        ((EdgeShape) lineFixture.shape).set(Vector2.Zero, new Vector2(200, 0));

        Body floor = world.createBody(bodyDefFloor);
        floor.createFixture(lineFixture);

        Body bird = world.createBody(bodyDefBird);
        bird.createFixture(circleFixture);
        bird.setUserData(BodyData.BIRD);

        Body rocket1 = world.createBody(bodyDefRocket1);
        rocket1.createFixture(rocketFixture);
        rocket1.setUserData(BodyData.ROCKET);

        Body rocket2 = world.createBody(bodyDefRocket2);
        rocket2.createFixture(rocketFixture);
        rocket2.setUserData(BodyData.ROCKET);

        renderer = new Box2DDebugRenderer();

        camera = new OrthographicCamera();

        world.setContactListener(new MyContactListener());

        rocketFixture.shape.dispose();
        circleFixture.shape.dispose();
        lineFixture.shape.dispose();
    }

    @Override
    public void render()
    {
        Gdx.gl.glClearColor(1, 0, 0, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

        world.step(1 / 60f, 8, 3);

        renderer.render(world, camera.combined);

        for (Body body : toBeDeletedBodies)
        {
            world.destroyBody(body);
        }

        toBeDeletedBodies.clear();
    }

    @Override
    public void dispose()
    {
        renderer.dispose();
        world.dispose();
    }
}

当您运行此示例时,您会看到地板上有一个圆圈(鸟)和两个掉落的矩形(火箭)。其中一个矩形击中圆并因此被破坏,另一个矩形没有被破坏。

关于java - 如何在碰撞时仅删除数组中的一个 Body? Libgdx,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33063231/

相关文章:

java - libGDX 使用贴花到面向 3d 的相机绘制文本

java - TextButton 背景上的 NinePatch 渲染问题 (libgdx)

java - 对于不同的 java 版本,写入和读取 png 图像必须相同

java - 尝试使用 2 个不同的按钮打开 2 个不同的 xml 页面

Java服务器端注释的REST客户端库

java - 从列表 Activity 中删除 ContentView

android - 如何仅向 URI 的创建者授予权限

java - 如何成功导入具有所有依赖项的 AndroidX 包?

java - 如何使用 httpUrlConnection 获取 url 的查询字符串,android

java - java和mysql中相同SQL查询的运行时间差异巨大