不同的Box2D机构以相同的质量表现出不同的意外行为

时间:2016-06-14 21:29:58

标签: java libgdx box2d

我有一个box2d机身,它只是一个矩形(宇宙飞船)。 这艘船飞行,受行星(静态圆体)的重力影响很好。

我尝试将船舶夹具形状更改为(1)三角形夹具和(2)两个矩形夹具放在一起。这两种身体配置都会引起问题。

考虑到体积的变化,为了弥补质量的差异,我计算了必要的新密度,以便这些物体具有与原始矩形体相同的质量。然而,当发射具有与以前相同的线性脉冲的船时,三角形主体和多矩形主体的行为与原始主体不同,向前射得更快。

我已经尝试进一步调整船舶密度以及线性冲量以及行星引力以使船舶恢复正常的行进速度, 然而,当这样做时,船开始表现得很奇怪,即使没有碰撞也会做突然在半空中切换方向的事情。当密度/重力/线性脉冲与以前完全相同时,这种看起来碰撞的事件不会发生,但是在那种情况下,船的移动速度太快,无法满足我的需求。

基本上我不知道为什么这些物体在质量没有变化或者除了形状和大小之外没有任何变化时表现不同。没有线性阻尼或碰撞发生。我不知道还有什么可能影响这艘船。

非常感谢任何帮助或想法。

以下是我认为相关的代码:

public void createShipBody() {
    density = 0.05f; //normal rectangle
    //density = 0.06666667f; //density for the two rectangles together
    restitution = 1.0f;
    bodyDef.type = BodyDef.BodyType.DynamicBody;

    setBodyDefPosition(bodyDef);
    body = GameCore.world.createBody(bodyDef);
    setShipShapeAndFixture();
}

// For with the original rectangle
private void setShipShapeAndFixture() {
    PolygonShape shape = new PolygonShape();
    shape.setAsBox(Utility.pixelsToMeters(bodyWidth / 2), Utility.pixelsToMeters(bodyHeight / 2));
    createFixtureDef(shape);
    shape.dispose();
}

// For with triangle fixture
private void setShipShapeAndFixture() {
    Vector2[] vertices = new Vector2[3];
    vertices[0] = new Vector2(0, 0);
    vertices[1] = new Vector2(Utility.pixelsToMeters(bodyWidth), 0);
    vertices[2] = new Vector2(Utility.pixelsToMeters(bodyWidth/2), Utility.pixelsToMeters(bodyHeight));
    shape.set(vertices);
    createFixtureDef(shape);
    shape.dispose();
}

// For multi-rectangle body
private void setShipShapeAndFixture() {
    PolygonShape shape = new PolygonShape();
    shape.setAsBox(Utility.pixelsToMeters(bodyWidth / 2), Utility.pixelsToMeters(bodyHeight / 4));
    PolygonShape shape2 = new PolygonShape();
    shape2.setAsBox(Utility.pixelsToMeters(bodyWidth / 4), Utility.pixelsToMeters(bodyHeight / 4), new Vector2(0, Utility.pixelsToMeters(bodyHeight/2)), 0);
    createShipMultiFixtureDef(shape, shape2);
    shape.dispose();
    shape2.dispose();
}

private void createFixtureDef(PolygonShape shape) {
    FixtureDef polygonFixtureDef = new FixtureDef();
    polygonFixtureDef.shape = shape;
    polygonFixtureDef.density = density;
    polygonFixtureDef.restitution = restitution;
    body.createFixture(polygonFixtureDef);
}

private void createShipMultiFixtureDef(PolygonShape shape, PolygonShape shape2) {
    FixtureDef polygonFixtureDef = new FixtureDef();
    polygonFixtureDef.shape = shape;
    polygonFixtureDef.density = density;
    polygonFixtureDef.restitution = restitution;
    FixtureDef polygonFixtureDef2 = new FixtureDef();
    polygonFixtureDef2.shape = shape2;
    polygonFixtureDef2.density = density;
    polygonFixtureDef2.restitution = restitution;
    body.createFixture(polygonFixtureDef);
    body.createFixture(polygonFixtureDef2);
}

/**
 * This is inside the Ship class
 * @param x From world center of release
 * @param y From world center of release
 * @param distance The capped distance of release from shipCenter, to determine force of impulse
 */
protected void applyLinearImpulse(float x, float y, float distance, float maxDistance) {
    float deltaX = x - getXinPixels();
    float deltaY = y - getYinPixels();

    float scale = 0.8f; // Have tried playing around with this with different bodies
    float force = scale * (distance/maxDistance);

    float angle = (float) Math.atan2(deltaY, deltaX);
    bodyWrapper.body.applyLinearImpulse(new Vector2((float) Math.cos(angle) * force,
            (float) Math.sin(angle) * force), getWorldCenter(), true);
}

// This is called on each planet every game update
protected void applyGravity() {
    for (SpaceObject spaceObject:spaceObjects) {
        float scalar = 2.334f;
        if(spaceObject instanceof Ship) {
            if (gameCore.shipInMotion) {
                scalar = 2f;    //Have tried playng with this for different bodies
            }
            else {
                continue; //No gravity to ship until it's launched
            }
        }
        Vector2 objectWorldCenter = spaceObject.getWorldCenter();
        Vector2 planetWorldCenter = getWorldCenter();
        float planetDiameter = Utility.pixelsToMeters(getWidth());
        float distance = Utility.distance(planetWorldCenter.x, planetWorldCenter.y, objectWorldCenter.x, objectWorldCenter.y);
        float xDistance =  planetWorldCenter.x - objectWorldCenter.x;
        float yDistance =  planetWorldCenter.y - objectWorldCenter.y;
        float x = (float) ((xDistance * planetDiameter * scalar) / (distance*distance));
        float y = (float) ((yDistance * planetDiameter * scalar) / (distance*distance));
        Vector2 gravity = new Vector2(x, y);
        spaceObject.bodyWrapper.body.applyForceToCenter(gravity, true);
    }
}

0 个答案:

没有答案