Libgdx 平铺地图 object 到 box2d body 位置

Libgdx Tiled map object to box2d body location

一张 Tiled 地图 object 以像素为单位的位置 x、y 和以度为单位的旋转。

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

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


背景:

使用代码:

 float angle = -rotation * MathUtils.degreesToRadians;
 bodyDef.angle = angle;
 bodyDef.position.set(x, y);

当旋转为 0 时有效,但当旋转不为 0 时 body 定位不正确。

我在这里找到了一些提示:

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

这里:

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

这似乎解决了这个确切的问题,但是这两种解决方案都不适合我,应用这些转换后 body object 仍然定位错误。定位错误我的意思是 body 位于地图上它应该在的区域,但根据其旋转 .

略有偏离

我觉得它应该很简单,但我不知道如何调解 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);

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

非常欢迎任何提示。

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

以上链接中的信息不正确and/or 已过时。当前 Tiled 根据其类型保存 object 位置。对于图像是相对于bottom-left位置。

Box2d 并没有真正的 "origin" 点,但您可以考虑它的中心,并且附加到 body 的固定装置的形状应该相对于 (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();

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

第 3 步:创建一个没有任何位置或角度的 body。

第 4 步:变换 body 位置和角度:

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

希望对您有所帮助。