I am new to Corona. I was trying to build a compass sort of a thing where I can rotate the needle by touch, for past some days. I have tried the code given in code exchange and many other places, but the rotation is not perfect. What I want is one end is fixed and I can touch and rotate the needle, that is in circle motion, just like when we are setting the time in the watch. Please help… [import]uid: 183447 topic_id: 32600 reply_id: 332600[/import]
This is a streamlined version of the code I use to spin my “Wheel of Fortune” type wheel in my trivia game OmniTrivia (http://omnitrivia.com) but should work for a touch event handler for anything you want to spin.
[code]
local function spinObject(event)
local t = event.target
local phase = event.phase
–print("Phase: " … 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
local angle1 = 180/math.pi * math.atan2(t.y1 - t.y , t.x1 - t.x)
local angle2 = 180/math.pi * math.atan2(t.y2 - t.y , t.x2 - t.x)
local rotationAmt = angle1 - angle2
t.rotation = t.rotation - rotationAmt
t.x1 = t.x2
t.y1 = t.y2
elseif (phase == “ended”) or (phase == “cancelled”) then
display.getCurrentStage():setFocus( nil )
t.isFocus = false
end
end
– Stop further propagation of touch event
return true
end
[/code] [import]uid: 19626 topic_id: 32600 reply_id: 129657[/import]
This works but the rotation is not perfect. In the above example the needle back end is not static, it also shows a slight movement from its initial postion while rotation, I want one end to be static. I am just unable to figure how to make one end static i.e, it does rotate but does not move from its position. [import]uid: 183447 topic_id: 32600 reply_id: 129658[/import]
IF you want this to be more clock like, where one point is the center of the dial and the other is near the numbers, you have to take your needle and basically in Photoshop extend the canvas so that you have emptyness extending past the center point. Then you may need to also have a mask to keep the other invisible end of the needle from being touch sensitive.
In other words, the part of the needle you want to stay anchored in the middle has to be the actual center of the image. [import]uid: 19626 topic_id: 32600 reply_id: 129673[/import]
This is a streamlined version of the code I use to spin my “Wheel of Fortune” type wheel in my trivia game OmniTrivia (http://omnitrivia.com) but should work for a touch event handler for anything you want to spin.
[code]
local function spinObject(event)
local t = event.target
local phase = event.phase
–print("Phase: " … 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
local angle1 = 180/math.pi * math.atan2(t.y1 - t.y , t.x1 - t.x)
local angle2 = 180/math.pi * math.atan2(t.y2 - t.y , t.x2 - t.x)
local rotationAmt = angle1 - angle2
t.rotation = t.rotation - rotationAmt
t.x1 = t.x2
t.y1 = t.y2
elseif (phase == “ended”) or (phase == “cancelled”) then
display.getCurrentStage():setFocus( nil )
t.isFocus = false
end
end
– Stop further propagation of touch event
return true
end
[/code] [import]uid: 19626 topic_id: 32600 reply_id: 129657[/import]
This works but the rotation is not perfect. In the above example the needle back end is not static, it also shows a slight movement from its initial postion while rotation, I want one end to be static. I am just unable to figure how to make one end static i.e, it does rotate but does not move from its position. [import]uid: 183447 topic_id: 32600 reply_id: 129658[/import]
IF you want this to be more clock like, where one point is the center of the dial and the other is near the numbers, you have to take your needle and basically in Photoshop extend the canvas so that you have emptyness extending past the center point. Then you may need to also have a mask to keep the other invisible end of the needle from being touch sensitive.
In other words, the part of the needle you want to stay anchored in the middle has to be the actual center of the image. [import]uid: 19626 topic_id: 32600 reply_id: 129673[/import]
You rock Rob - this made implementing a dial in my app super easy.
Here’s another (related) question: I want my dial to reveal a circular image below as it moves. Is there an easy way to do this?
Example image: https://dl.dropboxusercontent.com/u/9711036/Dial.png
Thanks,
Nathan.
Hi Nathan,
I think for that (considering the sample image you show), a mask would work, where you set the mask rotation depending on the rotation of the dial. I think you’ve worked with masks before, but if not, here’s a reference guide:
http://docs.coronalabs.com/guide/media/imageMask/index.html
Take care,
Brent
Thanks Brent. Yes - I’ve worked with masks before (with varying levels of success!).
If I make the mask a shape that shows the blue circle through and rotate it, it will need to be round, and will overlap on the other side of the circle until it rotates all the way around (if you know what I mean).
Should I use multiple mask images, and switch them as the rotation occurs?
Nathan.
Hi Nathan,
Another option, if your dial will look very similar to the sample, is to use a sprite animation and change frames as the dial moves along. Because the “handle” is quite big/wide, I think you would only need about 10-15 frames to handle every state of it… only updating the frame after the dial reaches a certain step threshold. As you mention, the mask approach gets tricky because of the distance it has to rotate, so I might suggest the sprite frame method instead.
Brent
Great idea Brent - I like the sprite idea and can envisage the implementation immediately.
Regards,
Nathan.
I’ve come across another challenge with this spinning code. I’m now using it to spin a steering wheel, then have the car react as a result.
I don’t understand why the “rotation” value of my item starts at 0, and sometimes:
-
goes up to 180 as I turn it to the right, and flicks to a negative value (say -179) when I get completely upside down, using negative values increasing to 0 as I continue to turn the item to the right and back to vertical (0).
-
goes up to some other value (say 43) as I turn to the right, then flicks to a large negative (-317), increasing to zero as I continue to turn to the right.
-
goes all the way to 360 as I turn to the right, and back to 0 when I return to the top.
It seems to change based on where on the wheel I grab to start turning. Bizarrely the car seems to take on the same rotation numbers at the same time (i.e. -55 on the wheel = -55 for the car, even though -55 may be a completely different on-screen angle in example 1 vs example 2).
Is there a way to make this consistent so that I can use the difference between the wheel rotation and the car rotation to define the torque that I want to apply to the car?
Thanks,
Nathan.
Hi Nathan,
You may want to try this code, which should control the “flick to opposite” behavior that you’re describing. This code calculates the angle between your object (at “srcX”/“srcY”) and a touch (at “dstX”/“dstY”), which may not be how your control actually works, but parts of the code can be parsed out and implemented as you see fit.
[lua]
local function angleBetween( srcX, srcY, dstX, dstY )
local angle = ( math.deg( math.atan2( dstY-srcY, dstX-srcX ) )+90 )
if ( angle < 0 ) then angle = angle + 360 end ; return angle % 360
end
[/lua]
Hope this helps,
Brent
Brent,
Woohoo - looks like the problem is fixed. I used your line “if ( angle < 0 ) then angle = angle + 360 end ; return angle % 360” to “fix” the angles being returned by rotation, so they reliably went from 0-360.
Thanks,
Nathan.
You rock Rob - this made implementing a dial in my app super easy.
Here’s another (related) question: I want my dial to reveal a circular image below as it moves. Is there an easy way to do this?
Example image: https://dl.dropboxusercontent.com/u/9711036/Dial.png
Thanks,
Nathan.
Hi Nathan,
I think for that (considering the sample image you show), a mask would work, where you set the mask rotation depending on the rotation of the dial. I think you’ve worked with masks before, but if not, here’s a reference guide:
http://docs.coronalabs.com/guide/media/imageMask/index.html
Take care,
Brent
Thanks Brent. Yes - I’ve worked with masks before (with varying levels of success!).
If I make the mask a shape that shows the blue circle through and rotate it, it will need to be round, and will overlap on the other side of the circle until it rotates all the way around (if you know what I mean).
Should I use multiple mask images, and switch them as the rotation occurs?
Nathan.
Hi Nathan,
Another option, if your dial will look very similar to the sample, is to use a sprite animation and change frames as the dial moves along. Because the “handle” is quite big/wide, I think you would only need about 10-15 frames to handle every state of it… only updating the frame after the dial reaches a certain step threshold. As you mention, the mask approach gets tricky because of the distance it has to rotate, so I might suggest the sprite frame method instead.
Brent
Great idea Brent - I like the sprite idea and can envisage the implementation immediately.
Regards,
Nathan.