Rotate a Physics Object

Hi

Just looking for a little help in rotating an object that is a physics object.  I have a line that is added as a physics object.  When another object is touched this line rotates by 45 degrees.  The rotation point is the corner of the line (e.g. I have moved the reference point from the centre to the edge).  This means that the once edge of the line stays still while the other edge drops.

I have a ball that falls onto the display.  When it hits this line, if it has been rotated it does not appear to follow the line (it bounces and follows the angle, but it is nowhere near the line).

I read in the help that if you rotate an object that is also a physics object then you could get spurious results. It states: -

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

However, it offers no explanation as to how you can rotate an object that is a physics object and get accurate results.

Can anyone help?

Just suggestion: make invisible/non-collision static object and create joint between it and your line.

OK, kind of get what you are saying, but how can I then move the line by a fixed amount.  I am looking to only move it 45 degrees, but this could be up or down.  If I use a joint can I still rotate it?

Oh only 45… joints have rotation limits but you want one specific angle… Is this line img or drawn? If drawn then maybe reference point cannot be changed?

It is an image.  I called it a line, but it is rectangle really.  The idea is that the user can move the ledge by 45 degress as the ball is falling or rolling over the ledge.  But the ledge is pivoting at its edge (e.g. it is dropping or possibly raising).  I thought I had something with the shape property of addBody, but it does not seem to be playing ball.

Rotating (or any other direct manipulation) of a physics object can be done in one of three different ways. None of these allow you to update the rotation or position of the physics body like you would a regular display object because you would be fighting the Box2D physics engine. To operate on objects in the physical world you must adhere to the rules of the physical world…

#1 - Directly: Turn off the physics body with .isBodyActive and manipulate the display object, then turn the physics body back on.

#2 - Fake touch: Connect a touch joint to the body and programmatically move the touch joint. This simulates a user’s touch, but is more precise because your code controls the motion. Increase the amount of max force to reduce the inaccuracy and make it look more explicit.

#3 - Motor: Assuming you want a motion that can be performed with a motor, just attach a joint to the body and use the motor. This is rather imprecise and can take a lot of fiddling around. If you don’t mind other objects colliding with the body and messing with the effect the joint’s motor is having on the body, you’ll be fine. Remember: the more force, the faster it will move - it’s simply not as controlled as the fake touch method.

IMHO: Fake touch. It’s got a high degree of control, provides better motions than a joint motor can (you can move things anywhere) and you don’t have to stop your body from affecting others.

Your problem: If I were you, I would attach a pivot to the point on your body where you want it to rotate around. Then attach a touch joint somewhere on the edge of the body. Use a simple bit of maths to rotate the touch joint smoothly and just keep updating the touch joint every frame.

The code below creates a square, attaches a touch joint to it and uses a display group (without physics) to calculate the rotation of the touch joint. An anchor body is used to keep the image in place. The solution avoids the need to use your own rotation calculations. It also uses a enterFrame listener to rotate the square and removes the listener when the rotation transition has finished.

require("physics") physics.start() physics.setGravity(0,10) local anchor = display.newCircle( -100,-100,10 ) physics.addBody(anchor,"static") local rect = display.newRect(0,0,200,200) rect.x, rect.y = display.contentCenterX, display.contentCenterY physics.addBody(rect,"dynamic") local pivotjoint = physics.newJoint("pivot",anchor,rect,display.contentCenterX, display.contentCenterY) local touchjoint = physics.newJoint("touch",rect,display.contentCenterX+200, display.contentCenterY) local easyturn = display.newGroup() easyturn.x, easyturn.y = display.contentCenterX, display.contentCenterY function enterFrame()     local x, y = easyturn:localToContent(200,0)     touchjoint:setTarget(x,y) end transition.to( easyturn, {time=10000,rotation=360, onComplete=function()     Runtime:removeEventListener("enterFrame",enterFrame) end} ) Runtime:addEventListener("enterFrame",enterFrame) 

Just suggestion: make invisible/non-collision static object and create joint between it and your line.

OK, kind of get what you are saying, but how can I then move the line by a fixed amount.  I am looking to only move it 45 degrees, but this could be up or down.  If I use a joint can I still rotate it?

Oh only 45… joints have rotation limits but you want one specific angle… Is this line img or drawn? If drawn then maybe reference point cannot be changed?

It is an image.  I called it a line, but it is rectangle really.  The idea is that the user can move the ledge by 45 degress as the ball is falling or rolling over the ledge.  But the ledge is pivoting at its edge (e.g. it is dropping or possibly raising).  I thought I had something with the shape property of addBody, but it does not seem to be playing ball.

Rotating (or any other direct manipulation) of a physics object can be done in one of three different ways. None of these allow you to update the rotation or position of the physics body like you would a regular display object because you would be fighting the Box2D physics engine. To operate on objects in the physical world you must adhere to the rules of the physical world…

#1 - Directly: Turn off the physics body with .isBodyActive and manipulate the display object, then turn the physics body back on.

#2 - Fake touch: Connect a touch joint to the body and programmatically move the touch joint. This simulates a user’s touch, but is more precise because your code controls the motion. Increase the amount of max force to reduce the inaccuracy and make it look more explicit.

#3 - Motor: Assuming you want a motion that can be performed with a motor, just attach a joint to the body and use the motor. This is rather imprecise and can take a lot of fiddling around. If you don’t mind other objects colliding with the body and messing with the effect the joint’s motor is having on the body, you’ll be fine. Remember: the more force, the faster it will move - it’s simply not as controlled as the fake touch method.

IMHO: Fake touch. It’s got a high degree of control, provides better motions than a joint motor can (you can move things anywhere) and you don’t have to stop your body from affecting others.

Your problem: If I were you, I would attach a pivot to the point on your body where you want it to rotate around. Then attach a touch joint somewhere on the edge of the body. Use a simple bit of maths to rotate the touch joint smoothly and just keep updating the touch joint every frame.

The code below creates a square, attaches a touch joint to it and uses a display group (without physics) to calculate the rotation of the touch joint. An anchor body is used to keep the image in place. The solution avoids the need to use your own rotation calculations. It also uses a enterFrame listener to rotate the square and removes the listener when the rotation transition has finished.

require("physics") physics.start() physics.setGravity(0,10) local anchor = display.newCircle( -100,-100,10 ) physics.addBody(anchor,"static") local rect = display.newRect(0,0,200,200) rect.x, rect.y = display.contentCenterX, display.contentCenterY physics.addBody(rect,"dynamic") local pivotjoint = physics.newJoint("pivot",anchor,rect,display.contentCenterX, display.contentCenterY) local touchjoint = physics.newJoint("touch",rect,display.contentCenterX+200, display.contentCenterY) local easyturn = display.newGroup() easyturn.x, easyturn.y = display.contentCenterX, display.contentCenterY function enterFrame()     local x, y = easyturn:localToContent(200,0)     touchjoint:setTarget(x,y) end transition.to( easyturn, {time=10000,rotation=360, onComplete=function()     Runtime:removeEventListener("enterFrame",enterFrame) end} ) Runtime:addEventListener("enterFrame",enterFrame)