How to get a rotation angle based on a SetLinearVelocity?

I am new to corona and have a little experience with programming.  I am currently fiddling around with the asteroid like tutorial game.  In this game it creates new asteroid at a random location and sets it on a random path (within specific bounds) using the code below:

 if ( whereFrom == 1 ) then -- From the left newAsteroid.x = -60 newAsteroid.y = math.random( 500 ) newAsteroid:setLinearVelocity( math.random( 40,120 ), math.random( 20,60 ) ) elseif ( whereFrom == 2 ) then -- From the top newAsteroid.x = math.random( display.contentWidth ) newAsteroid.y = -60 newAsteroid:setLinearVelocity( math.random( -40,40 ), math.random( 40,120 ) ) elseif ( whereFrom == 3 ) then -- From the right newAsteroid.x = display.contentWidth + 60 newAsteroid.y = math.random( 500 ) newAsteroid:setLinearVelocity( math.random( -120,-40 ), math.random( 20,60 ) ) end

I am trying to use the (newAsteroid.rotation =)  and set it to the specific angle of travel so that the images face the direction of travel.  I am having trouble figuring out how to change the x/y coordinates of the setLinearVelocity into an angle to use for the newAsteroid.rotation.  

Please help!  Thanks ahead of time!

Hi, Klynt.  I’ve been using the following function …

local atan2 = math.atan2 local rad2deg = 180 / pi -- calculate angle between 2 points ( clockwise ) local function calculateAngle( x1, y1, x2, y2 ) local dx = x2 - x1 local dy = y2 - y1 if dx == 0 or dy == 0 then if dx \> 0 then return 90 elseif dx \< 0 then return 270 elseif dy \> 0 then return 180 else return 0 end end return 90 + atan2( dy, dx ) \* rad2deg end

so, to make the object face the direction of travel, you can…

obj:setLinearVelocity( 6, -14 ) obj.rotation = calculateAngle( 0, 0, 6, -14 )

hope this helps!

fwiw, math.atan2 is well-behaved when x==0, and y==0 is not problematic, so you could eliminate that entire nested if statement.  (that sort of quadrant testing is often needed with math.atan though)

OP:  assuming the visual for your object points to true 0 (that is, when object.rotation = 0 it is “facing” right), then simply:  object.rotation = math.deg(math.atan2(y,x))

if the visual for your object (fe a bitmap sprite) instead points up (or some other angle) rather than right at zero rotation then you’ll have to add in an offset to correct for that “built-in” rotation to match the trig result.

This worked great.  My birds are rotated down so I had to do a -90.  Finished code is here…

local function createBird() local newBird = display.newImageRect( mainGroup, objectSheet, 1, 102, 85 ) table.insert( BirdsTable, newBird ) physics.addBody( newBird, "dynamic", { radius=40, bounce=0.8 } ) newBird.myName = "Bird" local whereFrom = math.random( 3 ) local randX local randY if ( whereFrom == 1 ) then -- From the left newBird.x = -60 newBird.y = math.random( 500 ) randX = math.random( 40,120 ) randY = math.random( 20,60 ) newBird:setLinearVelocity( randX, randY ) elseif ( whereFrom == 2 ) then -- From the top newBird.x = math.random( display.contentWidth ) newBird.y = -60 randX = math.random( -40,40 ) randY = math.random( 40,120 ) newBird:setLinearVelocity( randX, randY ) elseif ( whereFrom == 3 ) then -- From the right newBird.x = display.contentWidth + 60 newBird.y = math.random( 500 ) randX = math.random( -120,-40 ) randY = math.random( 20,60 ) newBird:setLinearVelocity( randX, randY ) end newBird.rotation = (math.deg(math.atan2(randY, randX)) -90) --This faces bird to direction of travel end

Hi, Klynt.  I’ve been using the following function …

local atan2 = math.atan2 local rad2deg = 180 / pi -- calculate angle between 2 points ( clockwise ) local function calculateAngle( x1, y1, x2, y2 ) local dx = x2 - x1 local dy = y2 - y1 if dx == 0 or dy == 0 then if dx \> 0 then return 90 elseif dx \< 0 then return 270 elseif dy \> 0 then return 180 else return 0 end end return 90 + atan2( dy, dx ) \* rad2deg end

so, to make the object face the direction of travel, you can…

obj:setLinearVelocity( 6, -14 ) obj.rotation = calculateAngle( 0, 0, 6, -14 )

hope this helps!

fwiw, math.atan2 is well-behaved when x==0, and y==0 is not problematic, so you could eliminate that entire nested if statement.  (that sort of quadrant testing is often needed with math.atan though)

OP:  assuming the visual for your object points to true 0 (that is, when object.rotation = 0 it is “facing” right), then simply:  object.rotation = math.deg(math.atan2(y,x))

if the visual for your object (fe a bitmap sprite) instead points up (or some other angle) rather than right at zero rotation then you’ll have to add in an offset to correct for that “built-in” rotation to match the trig result.

This worked great.  My birds are rotated down so I had to do a -90.  Finished code is here…

local function createBird() local newBird = display.newImageRect( mainGroup, objectSheet, 1, 102, 85 ) table.insert( BirdsTable, newBird ) physics.addBody( newBird, "dynamic", { radius=40, bounce=0.8 } ) newBird.myName = "Bird" local whereFrom = math.random( 3 ) local randX local randY if ( whereFrom == 1 ) then -- From the left newBird.x = -60 newBird.y = math.random( 500 ) randX = math.random( 40,120 ) randY = math.random( 20,60 ) newBird:setLinearVelocity( randX, randY ) elseif ( whereFrom == 2 ) then -- From the top newBird.x = math.random( display.contentWidth ) newBird.y = -60 randX = math.random( -40,40 ) randY = math.random( 40,120 ) newBird:setLinearVelocity( randX, randY ) elseif ( whereFrom == 3 ) then -- From the right newBird.x = display.contentWidth + 60 newBird.y = math.random( 500 ) randX = math.random( -120,-40 ) randY = math.random( 20,60 ) newBird:setLinearVelocity( randX, randY ) end newBird.rotation = (math.deg(math.atan2(randY, randX)) -90) --This faces bird to direction of travel end