【问题标题】:How does one make two bodies join together on the sides nearest the collision point in QML Box2D?如何让两个物体在 QML Box2D 中最靠近碰撞点的一侧连接在一起?
【发布时间】:2019-04-22 13:17:42
【问题描述】:

我有一个 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) }
     }

 }

每一个像它一样与另一个 Body 碰撞的对象都会被完全拉入碰撞的 Body 中,并且侧面根本不匹配。

我如何确定接触的实体的哪一侧以及如何连接它们的最佳方式?

【问题讨论】:

    标签: qt qml box2d


    【解决方案1】:

    我猜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
            }
        }
    }
    

    当然,您必须在这里调整距离和角度以满足您的需求。

    【讨论】:

    • 我明白了,使用 WeldJoint 而不是距离接头似乎确实使事情变得更好。也许我可以用你的例子来找出一种方法来匹配双方,以便碰撞的双方完全结合在一起——我将不得不把参数弄得一团糟……谢谢你的帮助
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多