Learn what Felgo offers to help your business succeed. Start your free evaluation today! Felgo for Your Business

Forums

OverviewFelgo 1 Support › Complex Box2D Components

Viewing 4 posts - 1 through 4 (of 4 total)
  • Author
    Posts
  • #4007

    Elisabeth

    Hello everyone,

    so far the Felgo demos, examples and docs demonstrate the basic usage of simple components. I wanted to build a more complex physics setup with multiple bodies and joints. In my case it’s a rope (BoxColliders + RevoluteJoints) dangling from a fixed body. When declared in the top-level qml file, everything works fine but the resulting file is quite confusing and hard to maintain. I tried to separate the rope part and created an EntityBase including the rope elements. As a result, only the first rope element behaves as expected while the other elements are somehow fixed to the first element (probably to the parent EntityBase).

    To boil down the question: What is the way to go if I want to build objects consisting of multiple bodies possibly connected with joints?

    Thanks for any advice,
    Thomas

    #4146

    Christian
    Felgo Team

    Hi Thomas,
    could you post some example code that works for you if defined in the top level file, and the one that does not work if you split it up?

    Cheers,
    Chris

    #4147

    Elisabeth

    Hi Christian,

    find enclosed my test case. There are two fixed bodies with each having a rope approximation (two BoxColliders connected via RevoluteJoints) attached. On the left side, everything is OK, but the code is contained in the top level qml file. On the right side you’ll see my naive attempt to separate the code – looks like stiff paranomal multiplexing (but: only one element is OK)…

    main.qml:

    
    import QtQuick 1.1
    import VPlay 1.0
    import Box2D 1.0
    
    GameWindow {
      id: window
      width: 960
      height: 640
    
      EntityManager {
        id: entityManager
        entityContainer: scene
      }
      
      Scene {
        id: scene
        width: 480
        height: 320
        sceneAlignmentY: "bottom"
    
        PhysicsWorld {
          id: physicsWorld
          z: 1
          height: parent.height
          updatesPerSecondForPhysics: 60
          gravity.y: -0.81
          velocityIterations: 5
          positionIterations: 5
        }
    
        /////////////////////////////////////////////////////////////
        // Without Rope Component
        /////////////////////////////////////////////////////////////
        EntityBase {
          id: fixedBody0
          x: physicsWorld.width / 3
          y: physicsWorld.height / 3
          
          property alias body: fixedBodyCollider0.body
    
          BoxCollider {
            id: fixedBodyCollider0
            anchors.centerIn: parent
            width: fixedBodyRect0.width
            height: fixedBodyRect0.height      
            bodyType: Body.Static
          }
         
          Rectangle {
            id: fixedBodyRect0
            width: 5
            height: 5
            color: "grey"
            anchors.centerIn: parent
          }
        }
    
        EntityBase {
          id: rod0
          x: physicsWorld.width / 3 + fixedBodyRect0.width / 2
          y: physicsWorld.height / 3 - fixedBodyRect0.height / 2
          width: 25
          height: 5
          transformOrigin: Item.TopLeft
    
          property alias body: rodCollider0.body
    
          BoxCollider {
            id: rodCollider0
            sleepingAllowed: false
            density: 1
            angularDamping: 1
          }
         
          Rectangle {
            id: rodRect0
            anchors.fill: parent
            color: "green"
          }
        }
    
        EntityBase {
          id: rod1
          x: physicsWorld.width / 3 + fixedBodyRect0.width / 2 + rod0.width 
          y: physicsWorld.height / 3 - fixedBodyRect0.height / 2
          width: rod0.width
          height: rod0.height
          transformOrigin: Item.TopLeft
    
          property alias body: rodCollider1.body
    
          BoxCollider {
            id: rodCollider1
            sleepingAllowed: false
            density: 1
            angularDamping: 1
          }
         
          Rectangle {
            id: rodRect1
            anchors.fill: parent
            color: "red"
          }
        }
    
        RevoluteJoint {
          id: revolute0
          bodyA: fixedBodyCollider0.body
          bodyB: rodCollider0.body
          world: physicsWorld
        }
    
        RevoluteJoint {
          id: revolute1
          bodyA: rodCollider0.body
          bodyB: rodCollider1.body
          world: physicsWorld
          localAnchorA: Qt.point(rodCollider0.width / 2, 0)
        }
    
    
        /////////////////////////////////////////////////////////////
        // With Rope Component
        /////////////////////////////////////////////////////////////
        Component.onCompleted: {
          entityManager.createEntityFromUrlWithProperties(Qt.resolvedUrl("Rope.qml"), {"anchorBody": fixedBody1.body, "x": physicsWorld.width / 3 * 2, "y": physicsWorld.height / 3});
        }
        
        EntityBase {
          id: fixedBody1
          x: physicsWorld.width / 3 * 2
          y: physicsWorld.height / 3
          
          property alias body: fixedBodyCollider1.body
    
          BoxCollider {
            id: fixedBodyCollider1
            anchors.centerIn: parent
            width: fixedBodyRect1.width
            height: fixedBodyRect1.height      
            bodyType: Body.Static
          }
         
          Rectangle {
            id: fixedBodyRect1
            width: 5
            height: 5
            color: "grey"
            anchors.centerIn: parent
          }
        }
    
      } // scene
    
    }
    

    Rope.qml:

    
    import QtQuick 1.1
    import VPlay 1.0
    import Box2D 1.0
    
    EntityBase {
      id: rope
    
      property variant anchorBody: null
      property double elementWidth: 25
      property double elementHeight: 5
    
      BoxCollider {
        id: rodCollider0
        width: elementWidth
        height: elementHeight
        x: 0
        y: -elementHeight/2
        sleepingAllowed: false
        density: 1
        angularDamping: 1
    
        Rectangle {
          anchors.fill: parent
          color: "green"
        }
      }
     
      BoxCollider {
        id: rodCollider1
        width: elementWidth
        height: elementHeight
        x: elementWidth
        y: -elementHeight/2
        sleepingAllowed: false
        density: 1
        angularDamping: 1
    
        Rectangle {
          anchors.fill: parent
          color: "red"
        }
      }
    
      RevoluteJoint {
        id: joint0
        bodyA: anchorBody
        bodyB: rodCollider0.body
        world: physicsWorld
      }
    
      RevoluteJoint {
        id: joint1
        bodyA: rodCollider0.body
        bodyB: rodCollider1.body
        world: physicsWorld
        localAnchorA: Qt.point(rodCollider0.width / 2, 0)
      }
    
    }
    

    As I don’t feel good with the experiments so far, I would be grateful for any hint pointing in the right direction.

    Cheers,
    Thomas

    #4203

    Christian
    Felgo Team

    Hi Thomas,

    it took me a while to figure out the issue here:

    Your comparsing between the 2 use-cases is actually not the same: for the first one where all works as expected, you use 2 separate entities for the middle and the bottom part that get connected with 2 ropes. For the second test, you only use 1 entity with 2 BoxColliders in it. And this is also the source of the problem: There must only be a single one BoxCollider, CircleCollider, etc. in a game entity. The reason for that is, that the entity position gets set to the one calculated for the collider. So if there are more than 1, the entity gets changed from 1 collider position to the other, and that’s why the screen is flickering.

     

    Long story short, please design your entities like in the first example, where you have the connecting entities with a BoxCollider, and then the RopeJoints as an own entity. You could write a QML file that handles the dynamic creation and destruction of the rope elements then, and which takes your desired input parameters specifying the rope (chain elements, lenght of each joint come into my mind).

    If you want multiple fixtures (e.g. a Box or a Circle is a fixture, and BoxCollider and CircleCollider are convenience wrappers by us as single colliders per entity are most common), you can derive your own physics components from ColliderBase. Please have a look at our implementation of BoxCollider.qml and CircleCollider.qml in the Felgo SDK sources, and also ColliderBase.qml will be for interest in that case for you. As a side note: did you think about how you will draw your rope parts then, because you would need to do all the transforms for each joint and connecting element manually.

    Does this solve your issue?

    Cheers,

    Chris

Viewing 4 posts - 1 through 4 (of 4 total)

RSS feed for this thread

You must be logged in to reply to this topic.

Qt_Technology_Partner_RGB_475 Qt_Service_Partner_RGB_475_padded