#### 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 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:

• 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()

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... ). 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()

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!