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.
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
@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:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
| --> 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 ) |
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.
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.
@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.
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
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.
Same problem here. Limbs get caught on corners and body torn apart in a morbid way :)
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..."
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
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).
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.
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...
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 :)
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 ! :)
N
The link for entry #6 is no longer available!!
@fdt40: link works for me.
So I tried Montage's solution and made all my static objects dynamic, and attached them to non-colliding static "anchor" invisible objects. While it did seem to improve the stretchy joints on the ragdoll somewhat it didn't remove the problem for especially hard/fast collisions, and adding an extra display object, physics body, and joint to fake each static object was way too slow on devices I tested on, for the # of objects I have in a level. It basically halved my framerate. As Montage said, I guess I am out of luck.
I have spent probably a week on this one particular problem without a satisfactory solution or workaround. It seemed like there was some traction with Ansca on this issue a few months ago. Are stretchy joints still being looked at as an issue, or are they working as intended?
@XenonBL
Same here. After spending a month on/off trying to work around these issues including countless experiments with various joints connections and tweaking of density, physics iterations, and such, it just looks like there are some thing that you can't do with Corona and you should either try to work this limits into your advantage by altering the gameplay where applicable or use another platform.
Some things that, at least for me, never worked and as such are out of question when Corona is in question are whatever physics that involve strong forces and collisions with joints, especially things like shooting ragdolls, ball-chains and such. I would love to see an example of Ragdoll-Blaster type of game, but I guess doing it you would need so much additional joints/static bodies, so many physics iterations and not to say countless hours of tweaking parameters that the whole thing may not be feasible.
But then again, believable physics is not an easy thing to do on any platform. What I learned from month of (mostly unsuccessfully) trying to fix these issues is that the good physics is as much (or more) a question of thoughtful game design as of skillful coding. By that I mean balancing all gameplay parameters so that the user never gets the chance to put the physics world in a state of illogical distress. So if your game is all about throwing things as forcefully as possible into joint-ridden structures (as one of my prototypes was) then I guess you really are out of luck. But if you can think of the ways to introduce subtle gameplay modifications that would guide user interactions to produce a more acceptable physic behavior, then you might not need to spend countless hours tweaking.
I am just starting to apply this advice to my own prototypes. While it might not still have produced acceptable results it's certainly more fun to spend time thinking and experimenting with gameplay itself rather than tweaking the parameters, so I'm already much better. Hope this helps a bit.
Cheers :)
@junk
Yeah, it's good advice in general. Every platform has its limitations, and you can either spend months trying to fit a square peg in a round hole or be clever and work your game design around the limitations. I guess what's frustrating for me is that some features in Corona only seem half implemented, or there are bugs that are not even acknowledged, so it's difficult to know what the true limitations are.
During my testing on the stretchy joints issue I discovered that weld joints can't be destroyed using removeSelf, and friction joints don't appear to function at all. So while there is definitely something flaky about Corona's version of Box2D, it's difficult to know if my problems are due to inherent limitations of Box2D, bugs in Corona's implementation, or my own ineptitude as a programmer.
The issue is that you already spent a considerable amount of time "investigating". In my case, I studied Lua from zero, then started developing for the game, the physics was left for the last part because I THOUGHT it would work fine, but it doesnt!
I managed to convince a partner for the project, now he is disappointed and wants to abort the project!
I dont get why we have to waste time with trial and error and at the end hit the wall anyways.
A pivot is something simple, but then doesnt work and you have to find a workaround.
I dont think is fair, if the guys of Ansca "promised" physics, we should have physics and pivot is the simplest form of it.. why it doesnt work like a charm!
So, seems that the physics promised by Ansca is just for balloons or pillars, but you try do do a simple ragdoll and ends up with the legs inside the body, trembling in the floor and not lying flat but as if he is doing push-ups instead.
Again, I think it is not fair.
Any update to any of this?
I am working on creating something like a pendulum or chained ball swinging for an iPad game - and even using these examples, things are really weird and buggy.
The joints seem to stick together somewhat at least, but I am facing another problem:
Basically, the pendulum keeps swinging forever - the force seems to be constant or decreasing so slowly that it seems constant. I mean, ideally i would like, say, 10 swings and then to see everything settle - but this seems to go into tens of thousands.
To me, it seems like this relates to the gravity - I've tried changing it to higher values, changing the density of my ball body to no luck. And setting the physics scale doesn't work either - according to the "width of a sprite in pixels and divide it by its real-world width" guide, at the scale I want things (something the size a yoyo pretty close-up), I need to set my scale to something in the 1000s which just makes everything super buggy.
You can see the same thing in the example codes posted, as far as I can see, and my code is basically the same.
So how would you create a rope pendulum that actually stops swinging?
I guess I'll have to work around it, so it saddens me that I might have to settle for something that's not nearly as good looking as I would like to because of weird physics implementations. Every project I've approached with something relating to physics has been filled with headaches because of the way everything has been implemented.
That said I am grateful for everything Corona allows me to do – I really love it and I'll stick with it!
Any news on this? I've spent the last two months learning lua/corona and now it seems that the physics will be a deal breaker!
The only 'working' example of a vehicle I've seen is 'Billy Cart', which is all very good but is a hack, is not using the correct joints and would not do for an actual driving game.
The second example at the link below is how joints should work - is this still not possible using Corona?
http://www.emanueleferonato.com/2009/04/06/two-ways-to-make-box2d-cars/
Thanks!