Pivot Joints and apparent elasticity

It’s cool you have some provided some better code for dragging stuff around but it does not address the core issue.

Corona is advertised as using Box 2d physics and it isn’t doing it correctly. This is major issue and causing a lot of developers to have major issues with their projects. Many don’t even know that is bug because they might think they are doing something wrong.

The ragdolls will still get hung up and have parts get separated whether dragged, flung or dropped in a simulation.

Try setting all of the joints to weld joints in that chain example and see the results. I tried to make a wheel joint and couldn’t get it to do what I want. I thought it was something that I was doing and now after seeing the piston joint problem I doubt it since the wheel inherits from the piston joint.

As far as I can tell pivot, weld, piston and wheel joints exhibit some type of problem with separation or lack of constraints.

How can you make a game similar to Angry Birds or Ragdoll Blaster 2 with this engines current problems? At least with any kind of real professional polish?

I would like to see this issue taken very serious and put as high priority among the Corona developer. This should take precedence above most things being worked like windows mobile sdk work or even new features.

I would like to hear opinions from other developers.

-Monte

[import]uid: 7531 topic_id: 3208 reply_id: 20474[/import]

I have had instances with bad joints that have nothing to do with touch joints of player interaction at all.

Here’s an easy test.

Make a rope.

Attach it to a static object.

Attach something dynamic to the other end

now drag stuff past the dynamic object

the rope unfailingly stretches out and it’s not hard to get to the point where the joints are separated by entire screen lengths and begin to go nuts

this is using rope construction techniques straight out of the example code, checked and triple checked [import]uid: 7473 topic_id: 3208 reply_id: 20475[/import]

While I would like to say that I do believe that the Corona SDK is the best available for the gamut it runs and the way it does, I have to agree with @montage and @desetto. The rag doll model (as well as the bridge sample, when many, many rocks are dropped) demonstrate something is very wrong and I believe this will turn away developers who have not found this issue in other SDK’s.

Matt. [import]uid: 8271 topic_id: 3208 reply_id: 20481[/import]

Thanks for the code tim. That seemed to work well. I noticed in the API reference joint.frequency and joint.dampingRatio says it is only used in distance joints. I guess it can be used in other types of joints as well?

I’m having trouble understanding the code sample.

 -- Apply optional joint parameters  
 if params then  
 local maxForce, frequency, dampingRatio  
   
 if params.maxForce then  
 -- Internal default is (1000 \* mass), so set this fairly high if setting manually  
 body.tempJoint.maxForce = params.maxForce  
 end  
  
 if params.frequency then  
 -- This is the response speed of the elastic joint: higher numbers = less lag/bounce  
 body.tempJoint.frequency = params.frequency  
 end  
  
 if params.dampingRatio then  
 -- Possible values: 0 (no damping) to 1.0 (critical damping)  
 body.tempJoint.dampingRatio = params.dampingRatio  
 end  
 end  

You say that params.frequency affects the response speed for less lag and bounce but where in your code can you make changes to this? The same with the dampingRatio?
Also here is a sample of a properly working prismatic/piston joint. Can you make a sample in Corona that shows this working properly? If it’s not a bug then I’m doing something wrong because I sure can’t figure it out. I’ve also posted a code sample and emailed you a code sample of what I’m talking about.

http://www.emanueleferonato.com/2009/02/03/box2d-joints-prismatic-joints/ [import]uid: 10243 topic_id: 3208 reply_id: 20518[/import]

It’s important to realize that Box2D performs real physical simulations. Therefore, you must be careful to understand what is happening physically.

So first thing’s first, the mass (as controlled by the “density” property) is critical. From a physical standpoint, the mass (via density) is where inertia comes from, meaning it determines how much it displaces due to momentum transfer.

This issue of mass is actually explained in the official Box2D documentation (Ch 13 of http://www.box2d.org/manual.html#_Toc258082979):

“Chains of bodies connected by joints may stretch if a lighter body is supporting a heavier body. For example, a wrecking ball connect to a chain of light weight bodies may not be stable. Stability degrades as the mass ratio passes 10:1.”

In order for a chain of bodies to not stretch, the density must be sufficiently high. That’s why in our Bridge sample code, there’s a lot of bounce — the density of the links is roughly the same as an individual boulder.

If you increase the density from 0.8 to 100, the bridge no longer stretches when the boulders fall. That’s b/c, physically, the mass of the links is so large that inertia wins over any momentum of the boulder.

Now, regarding the issue of dragging objects around and stretching, you can either operate within the laws of physics (touch joints) or outside the laws of physics (directly setting x,y of the display object).

I’ve looked at other non-Corona sample code, and they all consistently do the former, i.e. they use touch joints (aka “mouse” joints) just like Tim’s example above. With touch joints, you won’t see the kind of stretching or elasticity you do if you bypass Box2D and set the x,y property of the display object directly.

(As an aside, in various non-Corona forum discussions around Box2D), there’s mention of Box2D not liking the transforms for objects to be set directly, i.e. outside of Box2D, so it’s a miracle that directly setting transform properties of physics objects works in Corona at all!)

In terms of best practices, here are our recommendations:
* If you don’t want stretching, I recommend you use touch joints to allow the user to drag, like Tim’s example above.
* If you want a more ragdoll effect where stretching does occur as you drag the object around, then you should directly set x,y of the object to allow the user to drag, like @montage’s example above.

The best analogy I can come up with for the difference between the 2 dragging models is that with touch joints, Box2D applies a realistic force to the object, so you’ll get physically realistic effects, whereas if you directly set x,y then you are letting the user act like a supernatural being who operates above the laws of physics — in this case, you are applying what amounts to infinite forces, something no joint could possibly withstand.

Hope that helps!
walter
[import]uid: 26 topic_id: 3208 reply_id: 20521[/import]

@ericdg123, that drag function came from the gameUI library that’s in some of the sample code. I was looking at that too and it looks a little broken, since you can’t actually pass a params argument to the listener function when the event occurs.

One solution is to create a closure. Below is a modification of Tim’s example. You have a function (createDragBody) that creates another function (dragBody) that you pass as the listener. The created function (dragBody) is a closure b/c it stores values you passed to createDragBody. In the example below, I set the dampingRatio to 1.0:

[lua]–> Setup Display
display.setStatusBar (display.HiddenStatusBar)

–> Start Physics
local physics = require (“physics”)
physics.start ()
physics.setGravity (0, 10)

–physics.setDrawMode (“hybrid”)

–> Create Walls
local leftWall = display.newRect (0, 0, 1, display.contentHeight)
local rightWall = display.newRect (display.contentWidth, 0, 1, display.contentHeight)
local ceiling = display.newRect (0, 0, display.contentWidth, 1)
local floor = display.newRect (0, display.contentHeight, display.contentWidth, 1)

physics.addBody (leftWall, “static”, {bounce = 0.0, friction = 10})
physics.addBody (rightWall, “static”, {bounce = 0.0, friction = 10})
physics.addBody (ceiling, “static”, {bounce = 0.0, friction = 10})
physics.addBody (floor, “static”, {bounce = 0.0, friction = 10})

local xCenter = 160
local wCeil = 120
local hCeil = 20
local ceiling = display.newRect( xCenter - wCeil*0.5, 0, wCeil, hCeil )
physics.addBody( ceiling, “static”, { density=0, friction=0.5,bounce=0.2 } )

local prevBody = ceiling

local w,h = 10,50
local halfW,halfH = 0.5*w,0.5*h

– center of body
local x = xCenter
local y = hCeil - halfH
local yJoint = y - halfH

– rope
for i = 1, 5 do
y = y + h
yJoint = yJoint + h

local body = display.newRect( x-halfW, y-halfH, w, h )

body:setFillColor( 255, 0, 0, 128 )
physics.addBody( body, { density=50, friction=0.5, bounce=.2 })
local joint = physics.newJoint( “pivot”, prevBody, body, xCenter, yJoint )
prevBody = body
end

– final body
y = y + halfH
local r = h*0.5
local body = display.newCircle( x, y, r )
body:setFillColor( 0, 0, 255, 128 )
physics.addBody( body, { density=2, friction=0.5, bounce=.2, radius=r })
local joint = physics.newJoint( “pivot”, prevBody, body, xCenter, y )

local ball = body
local function createDragBody( params )
local function dragBody( event )
local body = event.target
local phase = event.phase
local stage = display.getCurrentStage()

if “began” == phase then
stage:setFocus( body, event.id )
body.isFocus = true

– Create a temporary touch joint and store it in the object for later reference
if params and params.center then
– drag the body from its center point
body.tempJoint = physics.newJoint( “touch”, body, body.x, body.y )
else
– drag the body from the point where it was touched
body.tempJoint = physics.newJoint( “touch”, body, event.x, event.y )
end

– Apply optional joint parameters
if params then
local maxForce, frequency, dampingRatio

if params.maxForce then
– Internal default is (1000 * mass), so set this fairly high if setting manually
body.tempJoint.maxForce = params.maxForce
end

if params.frequency then
– This is the response speed of the elastic joint: higher numbers = less lag/bounce
body.tempJoint.frequency = params.frequency
end

if params.dampingRatio then
print( “ratio”, params.dampingRatio )
– Possible values: 0 (no damping) to 1.0 (critical damping)
body.tempJoint.dampingRatio = params.dampingRatio
end
end
elseif body.isFocus then
if “moved” == phase then
– Update the joint to track the touch
body.tempJoint:setTarget( event.x, event.y )

elseif “ended” == phase or “cancelled” == phase then
stage:setFocus( body, nil )
body.isFocus = false

– Remove the joint when the touch ends
body.tempJoint:removeSelf()
end
end

– Stop further propagation of touch event
return true
end

return dragBody
end

local dragBody = createDragBody( { dampingRatio = 1.0 })
ball:addEventListener ( “touch”, dragBody )[/lua] [import]uid: 26 topic_id: 3208 reply_id: 20523[/import]

Much appreciated Walter and Tim. If you could address the piston/prismatic joint issue posted above and shed some of your insight on that I would be snug as a bug in a rug.

Judging from the complexity of the above responses and code, I am probably just doing something wrong or omitting something that needs to be there. [import]uid: 10243 topic_id: 3208 reply_id: 20539[/import]

Walter? Tim? I have sent an email and was told to respond with sample code, which I did. I still have not heard anything back.

Please help with the piston joint issue. [import]uid: 10243 topic_id: 3208 reply_id: 21180[/import]

@ericdg123, yes, there were issues with the piston joints. Essentially a unit conversion from screen pixels to box2d world units. Once daily builds are widely available, any daily build #280 or after should contain the fix. [import]uid: 26 topic_id: 3208 reply_id: 21504[/import]

#WIN [import]uid: 8271 topic_id: 3208 reply_id: 21685[/import]

I had a quick followup question regarding the elastic quality of joints when used on rag doll. I understand that increasing the density of chains will help prevent elastic behaviour in those joints. What i’m encountering however is an issue when a ragdoll collides with a static object.

What happens now, is when the ragdoll hits a static block, limbs will often get caught on the corners stretching the joint of the rag doll. Ideally, the rag doll would either get caught on the object, or slink around it.

I’m currently using pivot joints with a rope / character of high density and static platforms of low density (unsure if density even matters for static objects).

Does anyone know of a potential solution for this behaviour? As it stands, the rag doll’s functionality is potentially gamebreaking for my project.

Thanks!
-Nick [import]uid: 30416 topic_id: 3208 reply_id: 26785[/import]

I’m in same boat as marouhn. For example, if my ragdoll is falling and its head hits the corner of a static object, such as a rectangular brick, the body will continue to fall while the head remains stuck to the brick. At a certain point the head will snap back to the body, but for a second or two there is a rather large and growing space between the head and the rest of the body. It’s a very gruesome result for my otherwise family friendly game. I don’t want to earn an “M” rating due to “simulated decapitation” so I don’t think I can ship with this as is.

I’ve tried increasing body density 100x but get an identical result. I changed most physics bodies to spheres in hopes that there would be less corners for the ragdoll to get hung up on, and while that seems to help somewhat there are still many places where joints get stuck.

Ideally I’d like the ragdoll to slide around corners like a greased pig. But if not that at least have the object get hung up/stuck without the added injury of joint stretching.

If this isn’t an issue with other implementations of Box2D (when Googling “box2d pivot joints separating” this thread is near the top) then it seems likely there’s something broken with Corona’s version. Ansca, please take a closer look at this issue. [import]uid: 9422 topic_id: 3208 reply_id: 31181[/import]

Same problem here. Limbs get caught on corners and body torn apart in a morbid way :slight_smile:

Been playing around different densities and joint overlaps for a couple of days already. Did anybody find solution to this ? If not, apparent issues with physics engine will be a definite dealbreaker for me. I really like the workflow and APIs in Corona, but this implementation of physics engine is just too faulty and limiting, so it’s probably going to be for me:
“Good bye Corona, nice to see you again Cocos2D…”

[import]uid: 48785 topic_id: 3208 reply_id: 33466[/import]

The problem is that in Box2D pivot joints don’t play well with any static objects. It’s ok to have your borders as static objects or anything else that the ragdoll can’t get hung up on as static. You can have platforms or other objects but they must be dynamic. You can use pivot joints to attach the platform to a static object and make the static object not collide with anything. Now your ragdoll will not tear apart when iteracting with the platform. You can make it so the platform doesn’t rotate which will basicall lock it in place. You can use a weld joint or a pivot joint with body.isFixedrotation

The only problem is pivot joints aren’t that cheap. Maybe weld joints are cheaper? I haven’t tested that.

I hope this helps.

-Monte

[import]uid: 7531 topic_id: 3208 reply_id: 33473[/import]

With my ragdoll I’ve noticed increasing overall density does help with the joint separation problem. Also, try increasing the relative density of objects that tend to get hung up on static objects. For example, increasing the density of the head on my radgoll relative to the rest of the body parts removed the decapitation problem I was having. Once that problem went away the body getting stuck on static object corners became much less noticeable.

From my experience it seems that Box2D is just plain finicky about density. I’m not sure what the magic recipe is that prevents joint separation in Corona, other than to increase density, use 60 fps, and don’t hang high density objects off low density objects (such as a heavy wrecking ball off the end of a low density chain). [import]uid: 9422 topic_id: 3208 reply_id: 33486[/import]

Static object will apply infinite force to the joints so it doesn’t matter how much desity you use it can still cause separation.

We did a lot of experimentation to try and solve this problem as well.

Like I said above the only solution we came up with to keep this from happening is to only use dynamic objects even if they are fixed in your scene. This will solve the problem. If it isn’t a viable solution to your problem then I guess you’re out of luck.

Someone from Ansca should chime in on this. [import]uid: 7531 topic_id: 3208 reply_id: 33489[/import]

I almost emailed Carlos about this a few days ago because it is a big issue and if the solution is simply to do it a different way then someone should know. If the dynamic object solution what they use in flash? I find that hard to believe.

Of course, the dynamic object issue doesn’t solve things like isFixedRotation conflicting with the pivot joint, but that’s another issue… [import]uid: 8271 topic_id: 3208 reply_id: 33496[/import]

Montage, thanks for an interesting workaround. It does make sense from a real-world perspective that no object can realistically be static, but from engine perspective I am not sure that Box2D doesn’t take that into account.
The reason I say this is that I’ve been playing with various implementations of Box2D engine ( Flash, Cocos2D, OpenFrameworks ) and all across these platforms the results appeared consistent. I never seen such a drastic unexpected behavior as with Corona where it appears as if physics has a mind of its own, and a stubborn one.
So the time I am investing in trying to tame the wild physics is starting to slowly offset the time I gain by using Corona versus Cocos2D or even writing the game from scratch in pure C++.
Humm… I guess I am so frustrated because otherwise I really like Corona but these issues render it practically useless for a range of projects I am planning to do :slight_smile: [import]uid: 48785 topic_id: 3208 reply_id: 33546[/import]

Works Well With Dynamic Platforms
Hi again, just wanted to confirm that works well with using platforms as dynamic objects welded to static objects. Great stuff and out of the box(2D) thinking :), thanks again ! :slight_smile:
N [import]uid: 48785 topic_id: 3208 reply_id: 33603[/import]

The link for entry #6 is no longer available!! [import]uid: 41639 topic_id: 3208 reply_id: 38888[/import]