0
votes

I have a QML Box2D project that I'm working on which has a number of different Polygons in the form of Box2D Dynamic Bodies with Polygon Fixtures that all move dynamically around a World.

My goal is to make it so that whenever two different bodies collide with one another, they will both join on whatever sides that they collided on initially by matching the two sides up face to face and essentially joining into a single Body but remaining as two separate bodies in order to track them using the game's logic.

It will be something like two magnets floating in space and connecting to each other, and then having the two magnetic sides attracting one another and becoming fused together in a sense.

While I have had no issues creating the Bodies, and similarly no issues with determining when collisions happen and performing various functions when they do collide, I am not able to get the two objects to simply combine on a single side nearest the collision..

Here's what I've tried to do so far, without success:

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

 }

Every object that collides with another Body like it will simply become pulled into the colliding Body completely, and the sides do not match up at all.

How would I determine what the sides are of the Bodies that make contact and how is the best way to connect them?

1

1 Answers

1
votes

I guess WeldJoint fits much better, for example:

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

Sure, you have to play with distances and angles here to fit your needs.