physics and trigonometry little question

I apply a linear veloicty to an object linked to a point O to make the object turn around the point O.

It works but I still need some trigonometry feedback to solve my question.

Everything is explained in this image I made just for you :slight_smile:

https://dl.dropbox.com/u/67104046/vectors.png

Thx ! [import]uid: 9328 topic_id: 32669 reply_id: 332669[/import]

Hi.

Well, your object would be at position (relative to the origin):

x = radius * cos(angle), y = radius * sin(angle),

where angle is counter-clockwise starting from the x-axis. A little quick calculus gives you the tangent:

dx = -radius * sin(angle), dy = radius * cos(angle)

Since you’re going clockwise, you would flip the signs, and after incorporating your velocity you would have

dx = 100 * sin(angle), dy = -100 * cos(angle)

However , you don’t actually need to get the angle. In 2D you can get a perpendicular by switching x and y, and flipping the sign of one of them, as the above formulae show.

So your code would be something like

[lua]local dx, dy = object.x - O.x, object.y - O.y
local length = math.sqrt(dx * dx + dy * dy)
local scale = 100 / length

object:setLinearVelocity(dy * scale, dx * scale) – y is flipped again in screen space[/lua] [import]uid: 27791 topic_id: 32669 reply_id: 129916[/import]

Hi.

Well, your object would be at position (relative to the origin):

x = radius * cos(angle), y = radius * sin(angle),

where angle is counter-clockwise starting from the x-axis. A little quick calculus gives you the tangent:

dx = -radius * sin(angle), dy = radius * cos(angle)

Since you’re going clockwise, you would flip the signs, and after incorporating your velocity you would have

dx = 100 * sin(angle), dy = -100 * cos(angle)

However , you don’t actually need to get the angle. In 2D you can get a perpendicular by switching x and y, and flipping the sign of one of them, as the above formulae show.

So your code would be something like

[lua]local dx, dy = object.x - O.x, object.y - O.y
local length = math.sqrt(dx * dx + dy * dy)
local scale = 100 / length

object:setLinearVelocity(dy * scale, dx * scale) – y is flipped again in screen space[/lua] [import]uid: 27791 topic_id: 32669 reply_id: 129916[/import]

Wow ! That’s an answer ! Thank you :)) [import]uid: 9328 topic_id: 32669 reply_id: 129970[/import]

Wow ! That’s an answer ! Thank you :)) [import]uid: 9328 topic_id: 32669 reply_id: 129970[/import]

I’m back just to say I have somme issues with your sample code. I made a little code to show them :

[code]
display.setStatusBar( display.HiddenStatusBar );

local physics = require “physics”
physics.start()
physics.setGravity( 0, 0 )
–physics.setDrawMode( “hybrid” )

local center = display.newCircle( 160, 240, 40 )
physics.addBody( center, “static”, {density=1,radius=20,friction=0})

local function getPositions( x, y, angle, distance )
local mPi = math.pi;local mCos = math.cos;local mSin=math.sin; local mCeil=math.ceil
return { mCeil(x + (distance * mCos((angle-90) * mPi / 180))), mCeil(y + (distance * mSin((angle-90) *mPi / 180))) }
end

– the objects :
local function doObject ( angle, distance, index)

local indices = getPositions( 160, 240, angle, distance )
local object=display.newRoundedRect( indices[1], indices[2], 20,40, 4 )
object.rotation=angle

physics.addBody( object, “dynamic”, { isSensor = true, radius=20,density=1, friction=0, bounce=1 } )
object.joint = physics.newJoint( “pivot”, object, center, 160, 240 )

return object
end
local objects={}

for i=1, 2 do
objects[i]=doObject(i*30, 150,i)
end

local force = 1000

local function doRotation( event )

if event.phase == “began” then

for i=1,#objects do

objects[i]:setLinearVelocity( 0, 0 )

– your code :
local dx, dy = objects[i].x - 160, objects[i].y - 240
local length = math.sqrt(dx * dx + dy * dy)
local scale = force / length
objects[i]:setLinearVelocity(dy * scale, dx * scale)

– my problem :
– 1. objects should turn at the same speed …
– 2. objects should not change rotation sens

end
end
end

center:addEventListener(“touch”,doRotation) [/code]
[import]uid: 9328 topic_id: 32669 reply_id: 129985[/import]

I’m back just to say I have somme issues with your sample code. I made a little code to show them :

[code]
display.setStatusBar( display.HiddenStatusBar );

local physics = require “physics”
physics.start()
physics.setGravity( 0, 0 )
–physics.setDrawMode( “hybrid” )

local center = display.newCircle( 160, 240, 40 )
physics.addBody( center, “static”, {density=1,radius=20,friction=0})

local function getPositions( x, y, angle, distance )
local mPi = math.pi;local mCos = math.cos;local mSin=math.sin; local mCeil=math.ceil
return { mCeil(x + (distance * mCos((angle-90) * mPi / 180))), mCeil(y + (distance * mSin((angle-90) *mPi / 180))) }
end

– the objects :
local function doObject ( angle, distance, index)

local indices = getPositions( 160, 240, angle, distance )
local object=display.newRoundedRect( indices[1], indices[2], 20,40, 4 )
object.rotation=angle

physics.addBody( object, “dynamic”, { isSensor = true, radius=20,density=1, friction=0, bounce=1 } )
object.joint = physics.newJoint( “pivot”, object, center, 160, 240 )

return object
end
local objects={}

for i=1, 2 do
objects[i]=doObject(i*30, 150,i)
end

local force = 1000

local function doRotation( event )

if event.phase == “began” then

for i=1,#objects do

objects[i]:setLinearVelocity( 0, 0 )

– your code :
local dx, dy = objects[i].x - 160, objects[i].y - 240
local length = math.sqrt(dx * dx + dy * dy)
local scale = force / length
objects[i]:setLinearVelocity(dy * scale, dx * scale)

– my problem :
– 1. objects should turn at the same speed …
– 2. objects should not change rotation sens

end
end
end

center:addEventListener(“touch”,doRotation) [/code]
[import]uid: 9328 topic_id: 32669 reply_id: 129985[/import]

*Tries it out*

Ah, whoops. Disregard that " – y is flipped again in screen space". I was doing it all in my head and was SURE it needed to be that way. :stuck_out_tongue:

Instead. go with

dy * scale, -dx * scale

or

-dy * scale, dx * scale

At that point, the senses match up, and they approximately track each other, but not quite… and the drift accumulates. That may be inevitable with the physics involved, I don’t know. Maybe someone else would have a better idea here.

P.S. There’s a math.rad() in Lua’s standard library, so you can cut down the “(angle-90) * mPi / 180)” a little, if you want. [import]uid: 27791 topic_id: 32669 reply_id: 130066[/import]

*Tries it out*

Ah, whoops. Disregard that " – y is flipped again in screen space". I was doing it all in my head and was SURE it needed to be that way. :stuck_out_tongue:

Instead. go with

dy * scale, -dx * scale

or

-dy * scale, dx * scale

At that point, the senses match up, and they approximately track each other, but not quite… and the drift accumulates. That may be inevitable with the physics involved, I don’t know. Maybe someone else would have a better idea here.

P.S. There’s a math.rad() in Lua’s standard library, so you can cut down the “(angle-90) * mPi / 180)” a little, if you want. [import]uid: 27791 topic_id: 32669 reply_id: 130066[/import]

Ok, the “-” makes the difference indeed.

Thx [import]uid: 9328 topic_id: 32669 reply_id: 130158[/import]

Ok, the “-” makes the difference indeed.

Thx [import]uid: 9328 topic_id: 32669 reply_id: 130158[/import]

I’m back :slight_smile:

I must admit I still have a problem with my setLinearVelocity + pivotJoint launching system :
The rotating objects start fast but break strong and quite soon !
Let imaging this timeline with speed%, I have
100-60-40-20-20-20-10-10
I wish something smoother like :
100-100-90-90-80-80-70 …

Any hints from physic veteran :slight_smile: ? [import]uid: 9328 topic_id: 32669 reply_id: 133412[/import]

Hi Antheor,
I don’t mean to point out the “obvious”, but wouldn’t a simpler approach be to have those objects as long rectangles that actually have their center point equal to the circle’s center point, and then apply angular velocity to them? What the user “sees” could be independent of the actual physics body… an image with alot of transparent empty pixels, with only the “tip” as the drawn part. In regards to collision, if you needed ONLY the tip to collide with something, you could construct the bodies in 2 parts, with different collision filters preventing the “invisible” part from colliding with anything.

So, it might look like this… the “dashes” in the arms are invisible, but are still part of the physics body, which (as you can see) extends equally to the other side, with a central rotation point on the circle’s center. The “+” part of each arm is the visible tip.

 +  
 |  
---O--+  
 |  
 |  

Maybe I’m totally missing your desired result here, but would this solve it without resorting to joints and the angular force applications?

Brent
[import]uid: 200026 topic_id: 32669 reply_id: 133442[/import]

Hi Antheor, everybody,

Based on your approach, and the two problems you have:

  1. objects should not change rotation sense (clockwise / counterclockwise)

In the dx, dy component calculation, you do not take into account the object’s quadrant position related to the circle’s center. Since dx, dy can actually have positive or negative values based on the current position of the object, you have to take that into account by checking the object’s coordinates relative to the circle’s center, and calculate the impulse components vx, vy based on those values.

  1. objects should turn at the same speed

In the physics world, impulse is a momentum force which clearly looses its intensity over time. One approach to this is to have a function called by an infinite timer, that recalculates the actual coordinates of the revoluting object and readjusts the impulse vx, vy components and applies them to the object.

You do not specify exactly how you want to use this, but if you just use the revoluting objects as sensors, the following approach (slightly based on Brent’s idea) would work as well:

[lua]local physics = require(“physics”)
physics.start()

physics.setGravity(0,0)

background = display.newRect( 0, 0, display.contentWidth, display.contentHeight )
background:setFillColor( 0, 0, 0, 255 )

local circleRadius = 100

local circle = display.newCircle( display.contentWidth * 0.5, display.contentHeight * 0.5, circleRadius )
circle:setFillColor( 0, 0, 255, 255 )
circle.rotation = 0
physics.addBody( circle, “dynamic”)

local block = display.newCircle( circle.x, circle.y, 25, 25 )
block.x = circle.x + circleRadius
block.y = circle.y
block:setFillColor( 255, 255, 255, 255 )
physics.addBody( block, “dynamic”)

myJoint = physics.newJoint( “weld”, circle, block, block.x, block.y )

local function rotateBodies( event )
circle.rotation = circle.rotation + 2
end

timer.performWithDelay(10, rotateBodies, 0 )[/lua]

Hope all this helps,
Alex. [import]uid: 196533 topic_id: 32669 reply_id: 133455[/import]

Great ! Two new ideas : the angluar velocity on composed objects and the rotation with weld joints. I didn’t tought about none of them:)

I did try some pivot joint and rotation, but with bad results since box 2dupdate.

So, thank you.

Brent, you’re right I do need the “+” only to collide, still I’m not sure how to construct bodies in two parts.

Alexf, about turning at same speed, the fact that it’s not exactly the same speed is not a problem and the intensity loss is ok, it’s just that the loss is brutal.

Anyway, I’ll check your two solutions and be back for comments. [import]uid: 9328 topic_id: 32669 reply_id: 133521[/import]

Hi Antheor,
Glad to help. Here’s the documentation on complex (multi-part) physics bodies. Scroll down until you find “Complex body construction”.

http://developer.coronalabs.com/content/game-edition-physics-bodies

Note that each body part can have unique characteristics, including collision filters, isSensor true or false, etc. So, you can make the “invisible” part of the object null in regards to collision with other things, while the tip remains active and senses collision.

Also remember to use the .angularDamping property to set how soon your spinning object slows down (you mentioned wanting some control over that in the previous post).

Brent
[import]uid: 200026 topic_id: 32669 reply_id: 133523[/import]

God ! Where were you when I was struggling with this problem …
( here https://developer.coronalabs.com/forum/2012/09/28/yreference-and-physic-colision and here https://developer.coronalabs.com/forum/2012/09/05/physic-behavior-between-sdk-840-and-sdk-894 and here https://developer.coronalabs.com/forum/2012/06/30/pivot-revolution-madness)

Thank you sooooo much !

(still I have some work to do since I have to attach to “+” some objects (particle candy fields) that should move exactly like “+” visual) [import]uid: 9328 topic_id: 32669 reply_id: 133525[/import]

I’m back :slight_smile:

I must admit I still have a problem with my setLinearVelocity + pivotJoint launching system :
The rotating objects start fast but break strong and quite soon !
Let imaging this timeline with speed%, I have
100-60-40-20-20-20-10-10
I wish something smoother like :
100-100-90-90-80-80-70 …

Any hints from physic veteran :slight_smile: ? [import]uid: 9328 topic_id: 32669 reply_id: 133412[/import]

Hi Antheor,
I don’t mean to point out the “obvious”, but wouldn’t a simpler approach be to have those objects as long rectangles that actually have their center point equal to the circle’s center point, and then apply angular velocity to them? What the user “sees” could be independent of the actual physics body… an image with alot of transparent empty pixels, with only the “tip” as the drawn part. In regards to collision, if you needed ONLY the tip to collide with something, you could construct the bodies in 2 parts, with different collision filters preventing the “invisible” part from colliding with anything.

So, it might look like this… the “dashes” in the arms are invisible, but are still part of the physics body, which (as you can see) extends equally to the other side, with a central rotation point on the circle’s center. The “+” part of each arm is the visible tip.

 +  
 |  
---O--+  
 |  
 |  

Maybe I’m totally missing your desired result here, but would this solve it without resorting to joints and the angular force applications?

Brent
[import]uid: 200026 topic_id: 32669 reply_id: 133442[/import]

Hi Antheor, everybody,

Based on your approach, and the two problems you have:

  1. objects should not change rotation sense (clockwise / counterclockwise)

In the dx, dy component calculation, you do not take into account the object’s quadrant position related to the circle’s center. Since dx, dy can actually have positive or negative values based on the current position of the object, you have to take that into account by checking the object’s coordinates relative to the circle’s center, and calculate the impulse components vx, vy based on those values.

  1. objects should turn at the same speed

In the physics world, impulse is a momentum force which clearly looses its intensity over time. One approach to this is to have a function called by an infinite timer, that recalculates the actual coordinates of the revoluting object and readjusts the impulse vx, vy components and applies them to the object.

You do not specify exactly how you want to use this, but if you just use the revoluting objects as sensors, the following approach (slightly based on Brent’s idea) would work as well:

[lua]local physics = require(“physics”)
physics.start()

physics.setGravity(0,0)

background = display.newRect( 0, 0, display.contentWidth, display.contentHeight )
background:setFillColor( 0, 0, 0, 255 )

local circleRadius = 100

local circle = display.newCircle( display.contentWidth * 0.5, display.contentHeight * 0.5, circleRadius )
circle:setFillColor( 0, 0, 255, 255 )
circle.rotation = 0
physics.addBody( circle, “dynamic”)

local block = display.newCircle( circle.x, circle.y, 25, 25 )
block.x = circle.x + circleRadius
block.y = circle.y
block:setFillColor( 255, 255, 255, 255 )
physics.addBody( block, “dynamic”)

myJoint = physics.newJoint( “weld”, circle, block, block.x, block.y )

local function rotateBodies( event )
circle.rotation = circle.rotation + 2
end

timer.performWithDelay(10, rotateBodies, 0 )[/lua]

Hope all this helps,
Alex. [import]uid: 196533 topic_id: 32669 reply_id: 133455[/import]