Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

messing around with "physics labs" examples

edited July 2013 in Questions Posts: 277

I've been trying this for the best part of today...

In physics lab's test6, for example, I'm trying to swap wheels (I know, this is odd, but that's the simplest way to explain what I'm struggling with...)

If I touch the front wheel, I want the large rear wheel to take the place of the smaller, front wheel. I want them to keep all their respective properties, etc.

Is their a way to do this?

Would swapping bodies in the PhysicsDebugDraw tab do the trick? If so, how to accomplish this? I'm stuck here... :(

Cheers!

Tagged:

Comments

  • IgnatzIgnatz Mod
    edited July 2013 Posts: 5,396

    I'm guessing you'd need to swap the positions of the wheels wherever they are used (which seems to be in leftPos, leftWheel, and self.leftJoint) with the values for the right wheel

    you can swap leftPos for example, like this
    leftPos,rightPos=rightPos,leftPos

  • Posts: 277

    Thanks! I'm trying to get this to work, some quick attempts weren't successfull but I'm still on it. I guess my main issue is to really understand how bodies work, what's the importance of their orders in the bodies table, as well as the connection to what is drawn on top. Cheers!

  • Posts: 277

    Ok, so I tried several different things, and none seem to work correctly. The closest I'm getting to effectively swap two bodies (let me call them b1 et b2) in a physics simulation made of joints and circles is when I:

    1) list all existing joints connected to body b1 (I'll call the list c1)
    2) list all existing joints connected to object b2 (I'll call the list c2)
    3) erase all connections (in the simulation) from arrays c1 et c2
    4) rebuild c1 connections using object b2 as a starting point
    5) rebuild c2 connections using object b1 as a starting point
    6) swap x,y coordinates between b1 and b2

    I'm having several issues though:

    1) this works most of the time... Results are sometimes odd, and I'm suspecting that removing joints doesn't really work the way it should. I've tried joint:remove()
    2) I consider myself a rather bad coders, I code a bit here and there, but my methods are almost always the most convoluted, which leads me to think that here must be a most elegant, less tedious and, more importantly, less buggy way to accomplish this apparently simple operation in Codea.
    Don't you think?

    Here's my code :

    function PhysicsDebugDraw:swapBodies(b1,b2)
    c1 = {}
    c2 = {}

    c1 = b1.joints
    
    for i,v in pairs(c1) do
        if v.bodyA.id == b2.id or v.bodyB.id == b2.id then
            table.remove(c1,i)
        end
    end
    
    for i,v in pairs(c1) do
        if v.bodyB.id == b1.id then
            table.remove(c1,i)
            local edge = createEdge(v.bodyB,v.bodyA) -- THIS BUILT A 'DISTANCE' TYPE CONNECTION BETWEEN TWO BODIES
            table.insert(c1,edge)
        end
    end
    
    c2=b2.joints
    
    for i,v in pairs(c2) do
        if v.bodyA.id == b1.id or v.bodyB.id == b1.id then
            table.remove(c2,i)
        end
    end
    
    for i,v in pairs(c2) do
        if v.bodyB.id == b2.id then
            table.remove(c2,i)
            local edge = createEdge(v.bodyB,v.bodyA)
            table.insert(c2,edge)
        end
    end
    
    -- dewire
    print(table.getn(self.joints) .. " liens en tout")
    print(table.getn(c1) + table.getn(c2) .. " à enlever")
    for i,v in pairs(c1) do
        table.remove(self.joints,i)
        collectgarbage() -- DOES THIS EVEN DO ANYTHING?
        --v:destroy() -- DOESN'T SEEM TO WORK 
    end
    for i,v in pairs(c2) do
        table.remove(self.joints,i)
        collectgarbage()
        --v:destroy()
    end
    
    -- rewire
    for i,v in pairs(c1) do
        local edge = createEdge(b2,v.bodyB)
    end
    
    for i,v in pairs(c2) do
        local edge = createEdge(b1,v.bodyB)
    end
    
    temp = b1.position
    b1.position = b2.position
    b2.position = temp
    

    end


    end of code snippet

  • edited July 2013 Posts: 391

    Try something like this:

    See code below.

  • Posts: 391

    Tested the above code with 2 groups of 3 bodies connected by distance joints in a chain manner. It swapped perfectly.

  • edited July 2013 Posts: 391

    Here is the full project I used to test the above code:


    --# Main -- physics -- Use this function to perform your initial setup function setup() c1 = physics.body(CIRCLE,25) c1.position = vec2(200,500) c2 = physics.body(CIRCLE,25) c2.position = vec2(200,450) c3 = physics.body(CIRCLE,25) c3.position = vec2(200,400) c4 = physics.body(CIRCLE,25) c4.position = vec2(250,450) physics.joint(DISTANCE,c1,c2,c1.position,c2.position) physics.joint(DISTANCE,c2,c3,c2.position,c3.position) physics.joint(DISTANCE,c2,c4,c2.position,c4.position) d1 = physics.body(CIRCLE,25) d1.position = vec2(600,500) d2 = physics.body(CIRCLE,25) d2.position = vec2(600,450) d3 = physics.body(CIRCLE,25) d3.position = vec2(600,400) physics.joint(DISTANCE,d1,d2,d1.position,d2.position) physics.joint(DISTANCE,d2,d3,d2.position,d3.position) c1.active = false c2.active = false c3.active = false c4.active = false d1.active = false d2.active = false d3.active = false parameter.action("Swap", swap) body1 = {c1} body2 = {d1} getAllConnected(body1, c1) getAllConnected(body2, d1) end function swap() swapPosition(c1,d1) end -- This function gets called once every frame function draw() -- This sets a dark background color background(40, 40, 50) -- This sets the line thickness noStroke() -- Do your drawing here fill(0, 0, 255, 255) for _,v in pairs(body1) do ellipse(v.x, v.y, 15) end fill(255, 0, 0, 255) for _,v in pairs(body2) do ellipse(v.x, v.y, 15) end end --# Swap function swapPosition(b1,b2) local x = b2.x - b1.x local y = b2.y - b1.y bodies1 = {b1} bodies2 = {b2} getAllConnected(bodies1, b1) getAllConnected(bodies2, b2) for _,v in pairs(bodies1) do v.x = v.x + x v.y = v.y + y end for _,v in pairs(bodies2) do v.x = v.x - x v.y = v.y - y end end function getAllConnected(bodies, b) for _,v in pairs(b.joints) do local intable = false for _,vv in pairs(bodies) do if v.bodyB == vv then intable = true end end if not intable then table.insert(bodies, v.bodyB) getAllConnected(bodies, v.bodyB) end end end

    I added a 4th body to one of the 2 bodies so you can verify it is actually swapping all connected bodies.

    As you can see above, the getAllConnected function will work for drawing your bodies as well. Just don't forget to manually add the body being used to getAllConnected as it is not added to the table by the function, only the bodies recursively connected to it. However, if your bodies make a complete circle, then it will be recursively added, but manually adding it will not have it added twice, so I still suggest manually adding it.

  • Posts: 277

    Oh, that looks really nice. Thank you so much indeed. I've run your standalone example, and I have a hard time seeing how the code would behave with connections. Does it swap positions only, or also the connections that go with each swapped bodies (ok, that's not clear at all... in other words, in swapping A and B, does B inherits A's former connections, and vice versa? like on this very artistic rendering of what I'm looking to accomplish: https://www.dropbox.com/s/8u7yt4y2fnhppcp/Untitled artwork.jpg )

  • edited July 2013 Posts: 391

    @Rodolphe, I must have misunderstood what you were originally asking. My code will swap the positions of 2 separate bodies, each having multiple body connections of their own (the 2 bodies being swapped aren't connected at all). The recursive function is to make sure you get all the bodies attached to body1 and then all the bodies attached to body2 and swap positions. Like if you had created 2 separate human bodies, it would swap the positions of the 2 people.

    The only way to accomplish what is shown in your drawing is to do it how you already started to. You would have to figure out the bodies involved (my recursive function would still work for this) and then recreate each of them with their new connections.

    Back to the human example. So you are basically trying to swap an arm with a leg and make sure it reconnects correctly?

  • Posts: 277

    Ah ok @Slashin8r, this is what I thought. Thank you so much anyway, I did learn a few trick from your code. I am indeed trying to swap an arm with a leg (how odd does that sound... :D). I'll keep on working on my not-really-elegant-code then, using some of your recursive code to improve it (cheers for that!).

    By the way, what's the best way to effectively and instantly remove a joint from a physics simulation? removing the joint from the joints list and Garbage collecting? using destroy() on the joint? Something else?

  • edited July 2013 Posts: 391

    Here is a function that swaps the bodies and sets the new joints.


    --# Main -- physics -- Use this function to perform your initial setup function setup() c1 = physics.body(CIRCLE,25) c1.position = vec2(200,500) c2 = physics.body(CIRCLE,25) c2.position = vec2(200,450) c3 = physics.body(CIRCLE,25) c3.position = vec2(200,400) c4 = physics.body(CIRCLE,25) c4.position = vec2(250,450) physics.joint(DISTANCE,c1,c2,c1.position,c2.position) physics.joint(DISTANCE,c2,c3,c2.position,c3.position) physics.joint(DISTANCE,c2,c4,c2.position,c4.position) d1 = physics.body(CIRCLE,25) d1.position = vec2(600,500) d2 = physics.body(CIRCLE,25) d2.position = vec2(600,450) d3 = physics.body(CIRCLE,25) d3.position = vec2(600,400) physics.joint(DISTANCE,d1,d2,d1.position,d2.position) physics.joint(DISTANCE,d2,d3,d2.position,d3.position) c1.active = false c2.active = false c3.active = false c4.active = false d1.active = false d2.active = false d3.active = false parameter.action("Swap", swap) body1 = {c1} body2 = {d1} getAllConnected(body1, c1) getAllConnected(body2, d1) end function swap() print("Joints Before Swap") print("c2") for _,v in pairs(c2.joints) do local b if c2 == v.bodyA then b = v.bodyB else b = v.bodyA end print(b.x,b.y) end print("d2") for _,v in pairs(d2.joints) do local b if d2 == v.bodyA then b = v.bodyB else b = v.bodyA end print(b.x,b.y) end swapBodies(c2,d2) print("Joints After Swap") print("c2") for _,v in pairs(c2.joints) do local b if c2 == v.bodyA then b = v.bodyB else b = v.bodyA end print(b.x,b.y) end print("d2") for _,v in pairs(d2.joints) do local b if d2 == v.bodyA then b = v.bodyB else b = v.bodyA end print(b.x,b.y) end end -- This function gets called once every frame function draw() -- This sets a dark background color background(40, 40, 50) -- This sets the line thickness noStroke() -- Do your drawing here fill(0, 0, 255, 255) for _,v in pairs(body1) do ellipse(v.x, v.y, 15) end fill(255, 0, 0, 255) for _,v in pairs(body2) do ellipse(v.x, v.y, 15) end end --# Swap function swapBodies(b1,b2) joints1 = {} joints2 = {} for _,v in pairs(b1.joints) do local b if b1 == v.bodyA then b = v.bodyB else b = v.bodyA end table.insert(joints1, b) v:destroy() end for _,v in pairs(b2.joints) do local b if b2 == v.bodyA then b = v.bodyB else b = v.bodyA end table.insert(joints2, b) v:destroy() end b1.position,b2.position = b2.position,b1.position for _,v in pairs(joints1) do physics.joint(DISTANCE,b2,v,b2.position,v.position) end for _,v in pairs(joints2) do physics.joint(DISTANCE,b1,v,b1.position,v.position) end end function getAllConnected(bodies, b) for _,v in pairs(b.joints) do local intable = false for _,vv in pairs(bodies) do if v.bodyB == vv then intable = true end end if not intable then table.insert(bodies, v.bodyB) getAllConnected(bodies, v.bodyB) end end end

    The swapBodies function does the work and the swap function verifies it. getAllConnected is now only used to draw the bodies.

  • Posts: 277

    Great great great, thanks once again for you help, I'll try it later today.

  • Posts: 277

    Woohoo! It took me a while but I finally managed to get your excellent example to work in my project. Thanks a LOT!

Sign In or Register to comment.