代码之家  ›  专栏  ›  技术社区  ›  Aleris

Libgdx将对象平铺到box2d主体位置

  •  9
  • Aleris  · 技术社区  · 10 年前

    A. Tiled 贴图对象具有以像素为单位的位置x、y和以度为单位的旋转。

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

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


    背景:

    使用代码:

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

    旋转为0时有效,但当旋转不同于0时,主体未正确定位。

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

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

    这里:

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

        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 回复  |  直到 10 年前
        1
  •  0
  •   Aleris    10 年前

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

    上述链接中的信息不正确和/或过时。当前平铺根据对象的类型保存对象位置。对于相对于左下角位置的图像。

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

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

    步骤3:创建没有任何位置或角度的实体。

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

    希望有帮助。

    推荐文章