Rotating A Display Group, While Retaining Physics & Gravity?

I’m rotating a group of physics bodies.  It works great when the gravity is zero.  Once the gravity is turned on, it seems the gravitational field also rotates with the group, resulting in strange physics.  For example, the group of objects will not fall straight down while rotating; instead, it will spiral off the screen as it rotates. 

I didn’t understand what the following meant in the documentation for *.rotate:

  • “When a Display Object is converted into a physics object, rotating the Display Object will change the physical rotation but NOT affect the physics view of the object. This could result in unpredictable results when interacting with other physics bodies.”

So is there any way around this?  I have a group of physics objects arranged in a circular formation.  I want to have the entire group formation rotate, and also respond to normal physics and gravity. 

Thank you for your help…

The physics engine’s gravity is always relative to the parent display group’s coordinate system. This is enforced by the logic of the Box2D calculations and, if you think about it, is perfectly logical and reasonable. I battled with this for a while, but trust me: it is.

The core reason is that physics objects are NOT display objects - they are mathematically physics objects and essentially obey their own rules. That’s the short of it.

The reason that gravity appears to move with the display group’s rotation is that within the confines of that display group, x and y values have not changed - it is the rendering of the group within the screen which has changed, but the content of the group has not. In short: Down is still down, for display objects within that group.

The way round this is simply to not manipulate display groups when they contains physics objects - manipulate the physics objects directly. If you want to rotate the physics objects, you’ll need to work out how to do that, which is all up to your particular game or application’s logic, I’m afraid.

One thing you could do is to anchor them to a central (invisible) physics object with weld joints and then rotate the anchor object.

The physics engine’s gravity is always relative to the parent display group’s coordinate system. This is enforced by the logic of the Box2D calculations and, if you think about it, is perfectly logical and reasonable. I battled with this for a while, but trust me: it is.

The core reason is that physics objects are NOT display objects - they are mathematically physics objects and essentially obey their own rules. That’s the short of it.

The reason that gravity appears to move with the display group’s rotation is that within the confines of that display group, x and y values have not changed - it is the rendering of the group within the screen which has changed, but the content of the group has not. In short: Down is still down, for display objects within that group.

The way round this is simply to not manipulate display groups when they contains physics objects - manipulate the physics objects directly. If you want to rotate the physics objects, you’ll need to work out how to do that, which is all up to your particular game or application’s logic, I’m afraid.

One thing you could do is to anchor them to a central (invisible) physics object with weld joints and then rotate the anchor object.

Hi there,

I’ve also been trying to do this without success. The only resources I can find on this relate to the accelerometer gravity but that’s not what I want. I simply want to rotate a container (like the shape tumbler example but without the accelerometer) while retaining the overall gravity. It seems like a simple requirement but I guess not.

Did you happen to have any success with this?

Thanks

Hi Jack,

Do you just want to rotate a “bucket/container” with other objects rolling around inside? You should be able to do that easily enough by making it a multi-part physics body (you can’t have “holes” carved in a body in Box2D). Then, just rotate that object, while gravity remains the same… don’t try to rotate the display group that the bucket is contained in, as that will cause issues.

Does this help? Maybe I don’t fully understand the scenario you’re working on…

Best regards,

Brent

Hi Brent,

Thanks for your reply. Yes, that’s exactly what I’m trying to do. I was indeed making the mistake of creating my container as a display group and rotating that. I tried making it a multi-part physics body instead and it works now.

Thanks for the help,

Much appreciated,

Jack

After spending a bit of time with this I have spotted some problems with this implementation. I’m not sure whether it’s something I have done or haven’t done. I’ve implemented the bucket and inside I have two objects (a pentagon and a ball) to illustrate the problems:

Problem 1:

When I rotate the bucket to the right, both the pentagon and the ball move to the right as expected. At this point the bucket is tilted to the right. Now when I rotate the bucket back to the left, both objects begin to slide to the left but before the bucket has even tilted to the left. In fact they begin to slide left while the bucket is still tilted right. I know the gravity is ok because the ball will roll back to the right at this point if I stop the rotation while sill tilted to the right.

Here’s the code if anyone would like to try it and see:

local physics = require("physics") physics.start() physics.setScale( 60 ) physics.setGravity( 0, 9.8 ) -- initial gravity points downwards physics.setDrawMode( "hybrid" ) local bucket = display.newRect(0, 0, 100, 100) bucket.x = display.contentCenterX bucket.y = display.contentCenterY local bucket\_side\_r = { 130,0, 150,0, 150,200, 130,200 } local bucket\_bottom = { -150,195, 150,195, 150,215, -150,215 } local bucket\_side\_l = { -150,0, -130,0, -130,200, -150,200 } bucket\_density = 100.0 bucket\_friction = 100.0 bucket\_bounce = 0.0 physics.addBody( bucket, "static", { density=bucket\_density, friction=bucket\_friction, bounce=bucket\_bounce, shape=bucket\_side\_r}, { density=bucket\_density, friction=bucket\_friction, bounce=bucket\_bounce, shape=bucket\_bottom}, { density=bucket\_density, friction=bucket\_friction, bounce=bucket\_bounce, shape=bucket\_side\_l} ) local pentagon = display.newCircle(50, 200, 10) pentagonShape = { 0,-37, 37,-10, 23,34, -23,34, -37,-10 } physics.addBody( pentagon, "dynamic", { density=100.0, friction=100.0, bounce=0.0, shape=pentagonShape } ) pentagon.isSleepingAllowed = false local ball = display.newCircle(50, 200, 10) ball:setFillColor(192, 99, 55) ball.isSleepingAllowed = false physics.addBody(ball, "dynamic", {density=100.0, friction=.3, bounce=.6, radius=10}) ball.isBullet = true local function rotateBucket(event) local t = event.target local phase = event.phase if (phase == "began") then display.getCurrentStage():setFocus( t ) t.isFocus = true -- Store initial position of finger t.x1 = event.x t.y1 = event.y elseif t.isFocus then if (phase == "moved") then t.x2 = event.x t.y2 = event.y angle1 = 180/math.pi \* math.atan2(t.y1 - t.y , t.x1 - t.x) angle2 = 180/math.pi \* math.atan2(t.y2 - t.y , t.x2 - t.x) print("angle1 = "..angle1) rotationAmt = angle1 - angle2 --rotate it t.rotation = t.rotation - rotationAmt print ("t.rotation = "..t.rotation) t.x1 = t.x2 t.y1 = t.y2 elseif (phase == "ended") then display.getCurrentStage():setFocus( nil ) t.isFocus = false end end -- Stop further propagation of touch event return true end bucket:addEventListener("touch", rotateBucket)

Problem 2:

When I keep rotating the bucket the ball will eventually pass through the walls. I’ve spend a good while reading up on this and tried a lot of the suggestions but nothing seems to work. Many of the posts are old thought so I was just wondering if this there has been a fix for this since?

Things I’ve tried:

ball.isBullet = true

ball.isSleepingAllowed = false

physics.setPositionIterations(128)
physics.setVelocityIterations(128)

Slowing speed of rotation

Increasing densities

Nothing has solved the problem so far. Any help/advice for either problem would be greatly appreciated.

Thanks,

Jack

Hi Jack,

In situations that use multi-part physics bodies, I always ask the “obvious” question first: have you declared every custom shape/piece with the vertices going in clockwise order? I didn’t check your code… I’ll leave that to you… but it’s always the first thing to check when bodies are unexpectedly falling through other bodies.

Brent

Hi Brent,

Yes, I have declared the vertices of the bodies in clockwise order. I wonder are the problems a result of the way I’m rotating the bucket? I used a function I found here:

http://developer.coronalabs.com/code/rotate-object-finger

Other than that, it’s a very simple example.

Thanks,

Jack

Hi Jack,

I tested your scenario, and I’m not sure there’s a great solution for this, except to increase the thickness of the bucket walls. When you rotate the bucket that fast… sometimes 40-50 degrees change in just milliseconds… the objects can “pop” through the walls, despite all of your valid efforts to increase the collision frequency.

Maybe a better approach would be to attach a touch joint to the bottom of the bucket. Then, when the user touches/drags to the left or right sides, the touch joint pulls the bucket more gradually toward that point via a stretchy joint. This would help prevent the sudden, drastic, 40-50 degree angle changes that you have now, and hopefully keep the objects contained in the bucket. Now, that might not be how you imagined it working in gameplay, but it would probably solve the current issue(s).

Brent

Hi Brent,

Thank you for taking the time for testing my code. I understand what you’re saying about the fast movement but the code I posted only contained two objects to demonstrate the 2 problems I am having. In the real scenario I have the rotation slowed down but one of my objects is composed of a set of very small individual bodies tied together with joints. As the bodies are so small, even a slow rotation can cause some of them to pass through an obstacle and therefore ‘snag’ the entire body (since they are all connected with the joints). I will certainly have a look at implementing the touch joint scenario you suggested and see how that goes and report back.

In the meantime though, did you manage to see the effects of problem 1 I mentioned? Do you know of any reasons why this would be happening?

Thanks again for the help,

Jack

Hi Jack,

Is the object inside the bucket like a rag doll? If so, you might want to try disabling “continuous” physics detection. This can help reduce the instability that’s inherent to “rag doll” bodies, but it would require that you increase the thickness of your bucket walls… otherwise, the tunneling effect would probably be even more likely, not less.

http://docs.coronalabs.com/api/library/physics/setContinuous.html

Brent

Hi

I have a similar problem with groups and physics bodies. I’m draging a physic body and as I move it to the top of the screen, then I move the background downwards. My physics body and the background (no-physics) are in the same group. 

function moveCamera(e) if button3.y \< -lim.y + 300 then lim.y = -(button3.y - 300) end end Runtime:addEventListener("enterFrame", moveCamera)

But as I drag my physics object to the top of the screen and the background starts moving, then the dragging of the objects gets very unprecise, the object starts almost jumping around. 

Would it help, if I put also the backround as a physics body and completly avoid using groups? Or as Horacebury has said it:“One thing you could do is to anchor them to a central (invisible) physics object with weld joints and then rotate the anchor object.”. 

@tomaz4, you should really start a new thread for your question.

However, I suspect you are either moving the group which contains both the background and the physics object or use of the enterframe listener is the problem.

Are you trying to move the background and the dragged physics object relative to each other? If so, the maths for moving the background should really be relative to the position of the physics body in parent group and should be applied when a drag event occurs, not when the screen is refreshed (enterframe.)

Hi horacebury,

sorry for posting here. I thought it is a similar topic. I’m also kinda desperate, because I did open new topics but did not receive any feedback.

Yes, I’d like to move the background and my physics object at the same time and keep relative to each other. I use also a collision function between the two elements. For moving the objects I use this code, where allElements are the background and the physics object joined:

function runtimeListener(e) if head.y \< height - 300 then allElements.y = -(head.y - 300) end end Runtime:addEventListener("enterFrame", runtimeListener)

I’d did also put this function into the startDrag function(without the enterFrame), but it didn’t work out. 

You should provide a link in this thread to your question and ask for help, but…

Try not moving the camera and get everything else working first. Also, have you tried having code which moves things with a touch drag that are not physics objects?

aha, will do next time.

I also tryed moving the camera with an “ordinary” object and it worked fine. But the problem is, that my character has to a physical object. I also tryed to use the scrolling widget provided by corona. And again I have had the same problem. :frowning:

I think you should strip the code down to a single problematic demonstration - cut out everything not related to the functionality - and post a new thread (paste the url here) and we’ll look at that. At this point I’m trying to imagine your code, which is hard.

Here it is, at the end of the post. Thank you, for all your help and efforts.

http://forums.coronalabs.com/topic/35579-scrolling-and-dragging-bug/

Hi there,

I’ve also been trying to do this without success. The only resources I can find on this relate to the accelerometer gravity but that’s not what I want. I simply want to rotate a container (like the shape tumbler example but without the accelerometer) while retaining the overall gravity. It seems like a simple requirement but I guess not.

Did you happen to have any success with this?

Thanks