【问题标题】:Box2D crashes when destroying body (Expression: m_bodyCount < m_bodyCapacity)Box2D 在销毁 body 时崩溃(表达式:m_bodyCount < m_bodyCapacity)
【发布时间】:2014-07-22 19:43:11
【问题描述】:

表达式:m_bodyCount

这就是我遇到的错误。当我收到此错误时,整个游戏都崩溃了。现在,事情是这样的:我只在某些我试图摧毁,更具体地说,是在游戏中制造的身体时得到错误。我的意思是在游戏开始时,我加载关卡并为关卡的每个部分创建所有身体。但是,有些物品是在游戏运行时制作的,例如子弹、大炮和硬币。我可以销毁关卡加载时创建的任何主体,但是当我尝试销毁之后创建的主体时,我收到上述错误。

这是一个例子。我用我的 Cannon 生成了一个 CannonBall: Cannon.class

if(reloadProgress >= RELOAD_TIME) {
            CannonBall cannonBall = new CannonBall();
            cannonBall.setXDirection(xDirection);
            cannonBall.setYDirection(yDirection);
            cannonBall.position.set(cannonBallPos);
            Box2DHelper.makeFixture(cannonBall, BodyType.KinematicBody, origin, WorldController.b2world,
                    true, false);
            Level.cannonBalls.add(cannonBall);
            reloadProgress -= RELOAD_TIME;
        } else {
            reloadProgress += deltaTime;
        }

Box2DHelper.makeFixture() 在哪里:

public static void makeFixture(GameObject object, BodyType type,
            Vector2 origin, World b2world, boolean addUserData, boolean isMonster) {
        BodyDef bodyDef = new BodyDef();
        bodyDef.type = type;
        bodyDef.position.set(object.position);
        Body body = b2world.createBody(bodyDef);
        if(addUserData)
            body.setUserData(object);
        object.body = body;
        PolygonShape polygonShape = new PolygonShape();
        origin.x = object.bounds.width / 2.0f;
        origin.y = object.bounds.height / 2.0f;
        polygonShape.setAsBox(object.bounds.width / 2.0f,
                object.bounds.height / 2.0f, origin, 0);
        FixtureDef fixtureDef = new FixtureDef();
        fixtureDef.shape = polygonShape;
        if(isMonster) fixtureDef.filter.groupIndex = Constants.GROUP_MONSTER;
        body.createFixture(fixtureDef);
        polygonShape.dispose();
    }

所以现在我已经创建了我的 CannonBall 并设置了它的主体。现在,10 秒后,如果它没有击中任何东西,我将其摧毁:

CannonBall.class

if (existanceDuration >= CANNON_BALL_EXISTANCE_DURATION) {
            //Destroy cannon ball
            CollisionHandler.bodiesToRemoveList.add(this.body);
        }

现在我已将正文添加到列表中,我必须将其删除: CollisionHandler.class:

public static void removeSpecifiedBodies() {
        Iterator<Body> i = bodiesToRemoveList.iterator();
        while (i.hasNext()) {
            Body desBod = i.next();
            removeObjectFromList(desBod); //This is just to remove the object as well

            WorldController.b2world.destroyBody(desBod);

            if (perCharHitAction == true) {
                performCharacterDeathAction(Level.character);
                perCharHitAction = false;
            }
            i.remove();
        }
        bodiesToRemoveList.clear();
    }

但是现在,我需要真正调用这个方法。我在我的主要更新方法中执行此操作,就在 b2world.step() 之后: WorldController.class:

public void update(float deltaTime) {
        ...
        b2world.step(deltaTime, 8, 3);
        if (CollisionHandler.bodiesToRemoveList.size() > 0)
            CollisionHandler.removeSpecifiedBodies();

现在,就像我之前所说的,当我销毁在关卡加载时创建的对象时,此方法可以正常工作,但在我以后创建的对象上,它就不行了。

为什么我的游戏在尝试销毁后来在我的游戏中创建的 box2d 实体后不断崩溃?

编辑:我在关卡加载后立即调用此方法以创建对象的主体:

private void initPhysics() {
        if (b2world != null)
            b2world.dispose();
        b2world = new World(new Vector2(0, -9.81f), true);
        Vector2 origin = new Vector2();
        b2world.setContactListener(new CollisionHandler());

        // Create Box2D Fixtures
        for (Grass grass : Level.grasses)
            Box2DHelper.makeEdgeChain(grass, BodyType.StaticBody, origin,
                    b2world, true);

        // Bricks
        for (Brick brick : Level.bricks)
            // Box2DHelper.makeFixture(brick, BodyType.KinematicBody, origin,
            // b2world, true);
            Box2DHelper.makeEdgeChain(brick, BodyType.StaticBody, origin,
                    b2world, true);

        // Item Boxes
        for (ItemBox box : Level.itemBoxes)
            Box2DHelper.makeFixture(box, BodyType.KinematicBody, origin,
                    b2world, true, false);

        //Enemies
        for (Goomba goomba : Level.goombas)
            Box2DHelper.makeFixture(goomba, BodyType.DynamicBody, origin,
                    b2world, true, true);

        for (Koopa koopa : Level.koopas)
            Box2DHelper.makeFixture(koopa, BodyType.DynamicBody, origin,
                    b2world, true, true);

        // Cannons
        for (Cannon cannon : Level.cannons)
            Box2DHelper.makeFixture(cannon, BodyType.KinematicBody, origin,
                    b2world, true, true);


        // Character
        BodyDef bodyDef = new BodyDef();
        bodyDef.type = BodyType.DynamicBody;
        bodyDef.position.set(Level.character.position);
        Body body = b2world.createBody(bodyDef);
        body.setUserData(Level.character);
        Level.character.body = body;

        CircleShape polygonShapeHead = new CircleShape();
        origin.x = Level.character.circleBoundOrigin.x * 2.0f;
        origin.y = Level.character.circleBoundOrigin.y * 3.0f;
        // polygonShapeHead.setAsBox(level.character.circleBoundOrigin.x,
        // level.character.circleBoundOrigin.y, origin, 0);
        polygonShapeHead.setPosition(origin);
        polygonShapeHead.setRadius(Level.character.circleBoundOrigin.x);
        FixtureDef fixtureDefHead = new FixtureDef();
        fixtureDefHead.shape = polygonShapeHead;
        fixtureDefHead.friction = Level.character.friction.x;
        body.createFixture(fixtureDefHead);

        polygonShapeHead.dispose();

        PolygonShape polygonShapeBod = new PolygonShape();
        origin = Level.character.rectBoundOrigin;
        polygonShapeBod.setAsBox(Level.character.rectBoundOrigin.x,
                Level.character.rectBoundOrigin.y, origin, 0);
        FixtureDef fixtureDefBod = new FixtureDef();
        fixtureDefBod.shape = polygonShapeBod;
        fixtureDefBod.friction = Level.character.friction.x;
        body.createFixture(fixtureDefBod);

        polygonShapeBod.dispose();
    }

也许在游戏后期创建身体时的问题是 b2world?

【问题讨论】:

  • 我怀疑在加载关卡时制作的物体和之后制作的物体之间有什么不同?加载关卡时制作的实体是否都使用完全相同的程序?
  • 抱歉回复晚了。我很确定我正在以同样的方式制作它们。我只是调用 Box2DHandler 函数来创建它们。让我添加一个编辑,显示我在加载关卡时如何创建身体。
  • 我最终解决了这个问题。我没有将主体添加到我的 ContactListener 的销毁列表中,而是向对象添加了一个新的布尔值,并在我想销毁它们时将它们设置为 true。然后,在对象更新方法中,我将其添加到销毁列表中。这似乎已经解决了它。我认为这可能是从对象中获取主体或将其添加到联系人侦听器中的销毁列表的问题。

标签: java libgdx box2d


【解决方案1】:

我有同样的错误 - 我发现如果你多次破坏同一个身体就会发生这种情况。

在我的例子中,我将主体放入了联系人侦听器的列表中。但我并不确定它只在列表中出现过一次。

这也解释了为什么您的问题在使用布尔标志后得到解决,这也确保了同一个主体只被销毁一次。

简而言之:如果你试图一遍又一遍地摧毁同一个身体,你会得到这个错误。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-03-03
    • 2022-08-15
    • 1970-01-01
    • 1970-01-01
    • 2020-12-21
    • 2020-04-10
    相关资源
    最近更新 更多