#### Howdy, Stranger!

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

# DYNAMIC bodies connected by ROPE

edited February 2016 Posts: 20

OK this has been driving me nuts...

For a long time I thought I had a bug in my app and it was getting to me but after going back to the Physics Lab example I realised it wasn't me. I changed the joint between circle2 and the box to be a ROPE not a DISTANCE and confirmed my observation.

Two DYNAMIC bodies connected by a ROPE do not collide with each other but will hit other DYNAMIC bodies. Why is this so? Actually as I am typing this I can see a possible reason why this behaviour is so. If the maximum length of the ROPE joint is less than the distance between the outer edges of the two bodies we have a conundrum of two dynamic bodies overlapping and fighting each other with the ROPE constricting them.

My aim is to be able to drag multiple objects around with each object joined to the next with a ROPE so that they can bounce around but can only go a max distance from each other. I want those bodies to be able to knock each other around. Imagine dragging a string with beads tied at various locations along the length. If you move them around they hit each other.

Could someone please suggest how I can simulate this?

Thanks!

Tagged:

• Mod
Posts: 5,396

@toddixon - why don't you set up a minimal code example that demonstrates the problem and post it here, to give people something to play with.

• Mod
Posts: 5,396

You might want to look at the Box2D documentation and forums too, since that is what Codea uses.

• Posts: 634

It may be related to this issue, still not addressed....

https://codea.io/talk/discussion/comment/59113/#Comment_59113

• edited February 2016 Posts: 20

@Ignatz Thanks... Here's some code simulating the problem. Basically it's Physics Lab gutted for the purpose of illustrating what it's doing wrong for me.

Basically if you drag the first circle and move it around it will will collide with every other circle except for the one it is directly attached to. If you drag a different circle and attempt to hit other circles you will see varying effects.

I simply want every circle to collide with every other one using a ROPE-like effect.

``````supportedOrientations(LANDSCAPE_ANY)
function setup()
lineCapMode(ROUND)
debugDraw = PhysicsDebugDraw()
currentTest = Test()
currentTest:setup()
end

function createCircle(x,y,r)
local circle = physics.body(CIRCLE, r)
circle.interpolate = true
circle.type=DYNAMIC
circle.x = x
circle.y = y
circle.restitution = 0.25
circle.sleepingAllowed = false
return circle
end

function createGround()
local ground = physics.body(POLYGON, vec2(-50,20), vec2(-50,0), vec2(WIDTH+50,0), vec2(WIDTH+50,20))
ground.type = STATIC
return ground
end

function draw()
background(0, 0, 0)
debugDraw:draw()
end

function touched(touch)
debugDraw:touched(touch)
end

PhysicsDebugDraw = class()

function PhysicsDebugDraw:init()
self.bodies = {}
self.joints = {}
self.touchMap = {}
end

table.insert(self.bodies,body)
end

table.insert(self.joints,joint)
end

function PhysicsDebugDraw:draw()

pushStyle()
smooth()
strokeWidth(5)
stroke(128,0,128)

local gain = 2.0
local damp = 0.5
for k,v in pairs(self.touchMap) do
local worldAnchor = v.body:getWorldPoint(v.anchor)
local touchPoint = v.tp
local diff = touchPoint - worldAnchor
local vel = v.body:getLinearVelocityFromWorldPoint(worldAnchor)
v.body:applyForce( (1/1) * diff * gain - vel * damp, worldAnchor)
line(touchPoint.x, touchPoint.y, worldAnchor.x, worldAnchor.y)
end
stroke(0,255,0,255)
strokeWidth(5)
for k,joint in pairs(self.joints) do
local a = joint.anchorA
local b = joint.anchorB
line(a.x,a.y,b.x,b.y)
end
stroke(255,255,255,255)
noFill()
for i,body in ipairs(self.bodies) do
pushMatrix()
translate(body.x, body.y)
rotate(body.angle)

if body.type == STATIC then
stroke(255,255,255,255)
elseif body.type == DYNAMIC then
stroke(150,255,150,255)
elseif body.type == KINEMATIC then
stroke(150,150,255,255)
end

if body.shapeType == POLYGON then
strokeWidth(3.0)
local points = body.points
for j = 1,#points do
a = points[j]
b = points[(j % #points)+1]
line(a.x, a.y, b.x, b.y)
end
elseif body.shapeType == CHAIN or body.shapeType == EDGE then
strokeWidth(3.0)
local points = body.points
for j = 1,#points-1 do
a = points[j]
b = points[j+1]
line(a.x, a.y, b.x, b.y)
end
elseif body.shapeType == CIRCLE then
strokeWidth(3.0)
end
popMatrix()
end
stroke(255, 0, 0, 255)
fill(255, 0, 0, 255)
popStyle()
end

function PhysicsDebugDraw:touched(touch)
local touchPoint = vec2(touch.x, touch.y)
if touch.state == BEGAN then
for i,body in ipairs(self.bodies) do
if body.type == DYNAMIC and body:testPoint(touchPoint) then
self.touchMap[touch.id] = {tp = touchPoint, body = body, anchor = body:getLocalPoint(touchPoint)}
return true
end
end
elseif touch.state == MOVING and self.touchMap[touch.id] then
self.touchMap[touch.id].tp = touchPoint
return true
elseif touch.state == ENDED and self.touchMap[touch.id] then
self.touchMap[touch.id] = nil
return true
end
return false
end

Test= class()

function Test:init()
end

function Test:setup()
createGround()
local circle = createCircle(WIDTH/2, HEIGHT/2, 30)
local circle2 = createCircle(WIDTH/2+70, HEIGHT/2, 30)
local circle3 = createCircle(WIDTH/2+140, HEIGHT/2, 30)
local circle4 = createCircle(WIDTH/2+210, HEIGHT/2, 30)
local circle5 = createCircle(WIDTH/2+280, HEIGHT/2, 30)

local joint = physics.joint(ROPE, circle, circle2, circle.position,circle2.position,150)
local joint = physics.joint(ROPE, circle2, circle3, circle2.position,circle3.position,150)
local joint = physics.joint(ROPE, circle3, circle4, circle3.position,circle4.position,150)
local joint = physics.joint(ROPE, circle4, circle5, circle4.position,circle5.position,150)
end
``````
• edited February 2016 Posts: 1,595

@todddixon Hi there, I haven't been keeping up with Codea for a long time so it's nice to see new faces. I can't give you the code you need as I don't have an iPad or Codea atm.

This is easy to fix, if I can explain in clear terms. Say you have BoxA roped to BoxB, they pass through one another. Instead start off by not roping these two together.

If you create a third BoxC which must be smaller than boxA, position Box C in the center of BoxA give them the same angle. Once you've placed BoxC inside of BoxA you want to use physics.joint(WELD,..) between boxC and boxA to make sure that boxC is attached to the center of BoxA. Then you rope BoxC to BoxB and viola!

Here's an image in case that's not helping:

Also I forgot to mention you need to set boxC.sensor = true

• Mod
Posts: 9,260

@todddixon I had this example that does what you want. Instead of just one rope joint, you need several joints to form a rope. The more rope joints you have, the more it acts like a rope. This has 50 rope joints.

``````displayMode(FULLSCREEN)
supportedOrientations(PORTRAIT_ANY)

function setup()
tab={}  -- table of physics bodies
jnt={}  -- table of joints
j=50    -- number of joints
for z=1,j do
size=0
if z==1 or z==25 or z==j then
size=40
end
a=physics.body(CIRCLE,size)
a.x=200+z*8
a.y=HEIGHT-100
a.restitution=1.1
table.insert(tab,a) -- add bodies to table
if z>1 then -- create joint information and put in table
table.insert(jnt,physics.joint(ROPE,tab[z-1],tab[z],tab[z-1].position,
tab[z].position,8))
end
end
b1=physics.body(CIRCLE,20)
b1.x=400
b1.y=700
b1.type=STATIC
b2=physics.body(CIRCLE,20)
b2.x=470
b2.y=315
b2.type=STATIC
end

function draw()
background(40, 40, 50)
strokeWidth(2)
stroke(255)
for z=2,#tab do
line(tab[z].x,tab[z].y,tab[z-1].x,tab[z-1].y)   -- draw line between joints
end
fill(255,0,0)
ellipse(tab[1].x,tab[1].y,80)   -- draw circles on rope end
ellipse(tab[25].x,tab[25].y,80)
ellipse(tab[j].x,tab[j].y,80)
ellipse(b1.x,b1.y,40)
ellipse(b2.x,b2.y,40)
end
``````
• Posts: 9

Hi, been lurking here a bit. Trying to find any in this discussion.

• Posts: 9

Categories, there are no body.categories being used to discern or filter betwixt the bodies. That at least is partially responsible for the collision detection.

you said:

`````` Basically if you drag the first circle and move it around it will will collide with every other circle except for the one it is directly attached to. If you drag a different circle and attempt to hit other circles you will see varying effects.

I simply want every circle to collide with every other one using a ROPE-like effect.
``````

As far as the usage of physics.joints they are not supposed to directly interact with what they are directly attached to. Cause they are attached to it.

But if you want to restrict their movement range you might try tinkering with their upper and lower limits and setting them explicitly.

I don't want to say too much more cause I don't want to push you in a particular direction.

• Posts: 20

@Luatee @dave1707 @QMG Thanks for your input. I didn't think to get back to the discussion and instead started playing one evening and I eventually ended up with a solution that was basically the same suggestion from @Luatee except that interestingly it worked with all ROPEs and no WELDs. It was never actually a full rope-like effect I was after but after seeing the @dave1707 code I may choose to throw that effect in for the purpose I intend. Has all been good feedback. Cheers