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

如何使两个物体在离qml box2d中碰撞点最近的边上连接在一起?

  •  0
  • mike510a  · 技术社区  · 7 年前

    我有一个正在处理的qml box2d项目,它有许多不同的多边形,这些多边形以box2d动态实体的形式存在,多边形装置都在世界上动态移动。

    我的目标是这样做,当两个不同的身体彼此碰撞时,他们都会在最初碰撞的任何一边结合,通过面对面匹配两个身体,基本上结合成一个身体,但仍然是两个独立的身体,以便使用游戏的逻辑来跟踪他们。

    它有点像两块漂浮在空间中并相互连接的磁铁,然后两个磁性面相互吸引并在某种意义上融合在一起。

    虽然我没有创建实体的问题,同样也没有确定碰撞发生的时间和执行碰撞时的各种功能的问题,但我无法让两个对象简单地组合在离碰撞最近的一侧。

    以下是迄今为止我所做的尝试,但没有成功:

    Body {
        id: body
         world: physicsWorld
    
         property var vertices
         bodyType: Body.Dynamic
         target: gamePiece
    
         function beginContact(other) {
             if (other.getBody() !== wallBody) {
                 var newObject = Qt.createQmlObject('import QtQuick 2.9; import Box2D 2.0; DistanceJoint { }', body, "dynamicSnippet1");
                 newObject.bodyA = body;
                 newObject.bodyB = other.getBody();
                 newObject.length = 80;
                 DistanceJoint.collideConnected = true;
                 body.angularVelocity = 0;
                 body.fixedRotation = true;
                 console.log("Created Distance Joint " + newObject);
             } else {
                 console.log("Skipping Body collision with wall");
             }
         }
         fixtures: Polygon {
             density: 2
             friction: 0.9
             restitution: 0.01
             vertices: body.vertices
             onBeginContact: { body.beginContact(other) }
         }
    
     }
    

    每一个像它那样与另一个物体碰撞的物体都会被完全拉入碰撞的物体中,而且两个物体的侧面完全不匹配。

    我该如何确定身体接触的侧面是什么,以及连接它们的最佳方式是什么?

    1 回复  |  直到 7 年前
        1
  •  1
  •   folibis    7 年前

    我猜 WeldJoint 更适合,例如:

    import QtQuick 2.11
    import QtQuick.Window 2.11
    import Box2D 2.0
    
    Window {
        visible: true
        width: 800
        height: 600
        title: qsTr("Hello World")
        id: root
    
        World {
            id: physicsWorld
            gravity: Qt.point(0, 0)        
        }
    
        Repeater {
            model: [
                { "x": 0, "y": 0, "width": 10, "height": root.height },
                { "x": root.width - 10, "y": 0, "width": 10, "height": root.height },
                { "x": 10, "y": 0, "width": root.width - 20, "height": 10 },
                { "x": 10, "y": root.height - 10, "width": root.width - 20, "height": 10 }
            ]
            delegate: Rectangle {
                id: wall
                x: modelData.x
                y: modelData.y
                width: modelData.width
                height: modelData.height
                color: "lightgreen"
                Body {
                    bodyType: Body.Static
                    target: wall
                    fixtures: Box {
                        width: wall.width
                        height: wall.height
                        friction: 0.5
                        density: 0.5
                    }
                }
            }
        }
    
        Rectangle {
            id: item1
            height: 100
            width: 100
            color: "orange"
            antialiasing: true
            smooth: true
            x: 100
            y: 100
            Body {
                id: itemBody1
                bodyType: Body.Dynamic
                target: item1
                fixtures: Box {
                    density: 0.1
                    friction: 0.1
                    restitution: 1
                    width: item1.width
                    height: item1.height
                    onBeginContact: {
                        var body = other.getBody();
                        if(body === itemBody2)
                        {
                            var newJoint = linkJoint.createObject(root);
                            newJoint.bodyA = itemBody1;
                            newJoint.bodyB = body;
                        }                    
                    }
                }
            }
            Component.onCompleted: {
                var x = ((Math.random() * 800) - 400) / 200;
                var y = ((Math.random() * 600) - 300) / 200;
                itemBody1.applyLinearImpulse(Qt.point(x, y), Qt.point(50,50))
            }
        }
        Rectangle {
            id: item2
            height: 100
            width: 100
            color: "lightblue"
            antialiasing: true
            smooth: true
            x: 600
            y: 100
            Body {
                id: itemBody2
                bodyType: Body.Dynamic
                target: item2
                fixtures: Box {
                    density: 0.1
                    friction: 0.1
                    restitution: 1
                    width: item1.width
                    height: item1.height
                }
            }
            Component.onCompleted: {
                var x = ((Math.random() * 800) - 400) / 200;
                var y = ((Math.random() * 600) - 300) / 200;
                itemBody2.applyLinearImpulse(Qt.point(x, y), Qt.point(50,50))
            }
        }
        Component {
            id: linkJoint
            WeldJoint {
                localAnchorA: Qt.point(50, 50)
                localAnchorB: Qt.point(150, 150)
                collideConnected: true
            }
        }
    }
    

    当然,为了满足你的需要,你必须在这里练习距离和角度。