【问题标题】:How to remove just one Body exactly in array when collision? Libgdx碰撞时如何在数组中仅删除一个 Body? Libgdx
【发布时间】:2015-10-11 09:00:39
【问题描述】:

我正在使用 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);
          }
        }
    }

请帮帮我!

【问题讨论】:

  • 你的“bodyIsBoom()”方法是做什么的?似乎它将每个“身体”都标记为“繁荣”,而不仅仅是你想要的。
  • 如果 Body 是 Rocket Type (UserDataType.Rocket),该方法返回 true。仅适用于 BodyIsBird 之类的火箭(仅适用于 Bird)。我意识到 CollisionListener 类只是检测一个主体类型与另一个主体类型的碰撞,如果我们有多个(相同类型的数组主体),则不会准确返回该类型中的哪个主体。对不起我的英语

标签: java android libgdx collision-detection


【解决方案1】:

有了这个循环:

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) 评估为真)。

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

只需在您的 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 方法中破坏身体,因为它是在世界当前处于模拟状态时调用的,并且在此期间不得破坏身体,因为它可能导致不可预测行为。

编辑:

再次阅读您的问题后,我不确定我是否完全理解它,这就是为什么我创建了一个小而完整的示例,说明如何在接触时破坏身体:

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();
    }
}

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

【讨论】:

  • 真是个工作狂。非常感谢,非常感谢。当你能听懂我的英语时,我很兴奋。哈哈。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-10-25
  • 1970-01-01
  • 2015-02-07
  • 1970-01-01
  • 1970-01-01
  • 2014-02-01
  • 1970-01-01
相关资源
最近更新 更多