Libgdx将地图对象平铺到box2d的body位置

Ale*_*ris 9 box2d libgdx tiled

瓷砖地图对象帽子的位置的x,y中的像素和在度的旋转.

我正在从地图加载坐标和旋转,并尝试将它们分配给box2d Body.位置模型之间存在一些差异,例如Tiled对象旋转以度为单位,box2d体角度为弧度.

如何将位置转换为BodyDef坐标x,y和角度,以便在正确的位置创建正文?


背景:

使用代码:

 float angle = -rotation * MathUtils.degreesToRadians;
 bodyDef.angle = angle;
 bodyDef.position.set(x, y);
Run Code Online (Sandbox Code Playgroud)

当旋转为0时工作,但当旋转不同于0时,正文未正确定位.

我在这里找到了几个提示:

http://www.tutorialsface.com/2015/12/qu ... dx-resolved /

和这里:

https://github.com/libgdx/libgdx/issues/2742

这似乎解决了这个确切的问题,但是这两种解决方案对我来说都没有用,在应用这些转换后,身体对象仍然处于错误状态.如果定位错误,我的意思是身体位于地图区域应该是,但根据其旋转稍微偏离.

我觉得它应该很简单,但我不知道如何调解Tiled和box2d位置之间的差异.

作为参考,这些是我从上面的链接尝试的两个解决方案(在将值x,y,宽度,高度从像素转换为世界单位之后):

float angle = rotation * MathUtils.degreesToRadians;
bodyDef.angle = -angle;
Vector2 correctionPosition = new Vector2(
        height * MathUtils.cosDeg(-rotation - 90),
        height + height * MathUtils.sinDeg(-rotation - 90));
bodyDef.position.set(x, y).add(correctionPosition);
Run Code Online (Sandbox Code Playgroud)

    float angle = rotation * MathUtils.degreesToRadians;

    bodyDef.angle = -angle;

    // Top left corner of object
    Vector2 correctedPosition = new Vector2(x, y + height);

    // half of diagonal for rectangular object
    float radius = (float)Math.sqrt(width * width + height * height) / 2.0f;

    // Angle at diagonal of rectangular object
    float theta = (float)Math.tanh(height / width) * MathUtils.degreesToRadians;

    // Finding new position if rotation was with respect to top-left corner of object.
    // X=x+radius*cos(theta-angle)+(h/2)cos(90+angle)
    // Y=y+radius*sin(theta-angle)-(h/2)sin(90+angle)
    correctedPosition = correctedPosition
            .add(
                    radius * MathUtils.cos(theta - angle),
                    radius * MathUtils.sin(theta - angle))
            .add(
                    ((height / 2) * MathUtils.cos(MathUtils.PI2 + angle)),
                    (-(height / 2) * MathUtils.sin(MathUtils.PI2 + angle)));

    bodyDef.position.set(correctedPosition);
Run Code Online (Sandbox Code Playgroud)

任何暗示都会受到高度欢迎.

Ale*_*ris 0

找到了正确的解决方案,损失了我大约 1 天的生命:)

上述链接中的信息不正确和/或已过时。目前,Tiled 根据对象的类型保存对象位置。因为图像是相对于左下位置的。

Box2d 实际上没有“原点”点,但您可以考虑它的中心,并且连接到主体的固定装置的形状应相对于 (0,0) 定位。

第 1 步:读取平铺属性

        float rotation = textureMapObject.getRotation();

        float x = textureMapObject.getX();
        float y = textureMapObject.getY();

        float width = textureMapObject.getProperties()
            .get("width", Float.class).floatValue();
        float height = textureMapObject.getProperties()
            .get("height", Float.class).floatValue();
Run Code Online (Sandbox Code Playgroud)

步骤 2:根据您的 box2d 世界大小缩放这些,例如 x = x * 1/25;ETC。

第三步:创建一个没有任何位置或角度的物体。

步骤 4:通过以下方式变换身体位置和角度:

    private void applyTiledLocationToBody(Body body, 
        float x, float y, 
        float width, float height, 
        float rotation) {
    // set body position taking into consideration the center position
    body.setTransform(x + width / 2, y + height / 2, 0);

    // bottom left position in local coordinates
    Vector2 localPosition = new Vector2(-width / 2, -height / 2);

    // save world position before rotation
    Vector2 positionBefore = body.getWorldPoint(localPosition).cpy();

    // calculate angle in radians
    float angle = -rotation * MathUtils.degreesToRadians;

    // set new angle
    body.setTransform(body.getPosition(), angle);

    // save world position after rotation
    Vector2 positionAfter = body.getWorldPoint(localPosition).cpy();

    // adjust position with the difference (before - after) 
    // so that the bottom left position remains unchanged
    Vector2 newPosition = body.getPosition()
            .add(positionBefore)
            .sub(positionAfter);
    body.setTransform(newPosition, angle);
}
Run Code Online (Sandbox Code Playgroud)

希望能帮助到你。