Dial not behaving

I hope someone can help me here as I seem to be getting turned around…

I have a container group, into which I add a small circle to be a static object to use as the base for a pivot joint. Then into the same group I add another group - the dial - into which I add a large circle and a small dot show represent direction. I then add bodies to the pivot circle in the outer group and to the dial group itself.

I then add a pivot joint to the static circle and the dynamic dial. This should allow the dialcontainer (the outer group) the be moved around the screen, but also allow drag touches on the dial’s large circle to rotate the dial.

Unfortunately, while I can get the dial behaving anywhere I want to, once it has it’s bodies and joints attached, I cannot move it around the screen. Code follows…

[lua]local physics = require( “physics” )
physics.start()
physics.setGravity( 0, 0 )
physics.setDrawMode( “hybrid” ) – normal, hybrid, debug
local dialcontainer = display.newGroup()
–dialcontainer.x, dialcontainer.y = display.contentCenterX, display.contentCenterY

dialcontainer.pivot = display.newCircle( dialcontainer, display.contentCenterX, display.contentCenterY, 5 )
local dial = display.newGroup()
dialcontainer:insert( dial )

dial.x, dial.y = display.contentCenterX, display.contentCenterY

dial.wheel = display.newCircle( dial, 0, 0, 150 )
dial.wheel:setFillColor( 0, 255, 0, 155 )

dial.dot = display.newCircle( dial, 0, 145, 2.5 )
dial.dot:setFillColor( 255, 0, 0, 255 )
physics.addBody( dialcontainer.pivot, “static”, { friction=0, density=0, bounce=0 } )
physics.addBody( dial, “dynamic”, { friction=0, density=0, bounce=0, radius=150 } )

dialcontainer.pivotjoint = physics.newJoint( “pivot”, dialcontainer.pivot, dial, display.contentCenterX, display.contentCenterY )
function dragBody( event )
local body = event.target
local phase = event.phase
local stage = display.getCurrentStage()

if “began” == phase then
stage:setFocus( body, event.id )
body.isFocus = true

– Create a temporary touch joint and store it in the object for later reference
body.tempJoint = physics.newJoint( “touch”, body, event.x, event.y )

elseif body.isFocus then
if “moved” == phase then

– Update the joint to track the touch
body.tempJoint:setTarget( event.x, event.y )

elseif “ended” == phase or “cancelled” == phase then
stage:setFocus( body, nil )
body.isFocus = false

– Remove the joint when the touch ends
body.tempJoint:removeSelf()

end
end

– stop further propagation of touch event
return true
end

dial:addEventListener( “touch”, dragBody )[/lua]

Thanks for any help,

Matt. [import]uid: 8271 topic_id: 5373 reply_id: 305373[/import]

Well, I’m not massively happy about it, but moving the first body, instead of it’s parent display group, does the trick. This makes sense, as joints are dictated by bodies and not display groups, but it is somewhat irritating as it will mean that a more complex interface mechanism will be needed later (other plans to follow…)

I’m not happy about it, because moving the anchor of the pivot joint (the first circle) only moves the anchor. A further interaction is apparently required to shift the thing jointed to it. I manage this using a fake touch event, but that stops the spinning of the dial, if it is spinning. I would prefer a spinning dial to be able to move without stopping - it seems inelegant this way.

Working code which moves the dial to the tap point:

[lua]local physics = require( “physics” )
physics.start()
physics.setGravity( 0, 0 )
physics.setDrawMode( “hybrid” ) – normal, hybrid, debug

local dialcontainer = display.newGroup()

dialcontainer.pivot = display.newCircle( dialcontainer, display.contentCenterX, display.contentCenterY, 5 )
local dial = display.newGroup()
dialcontainer:insert( dial )

dial.x, dial.y = display.contentCenterX, display.contentCenterY

dial.wheel = display.newCircle( dial, 0, 0, 150 )
dial.wheel:setFillColor( 0, 255, 0, 155 )

dial.dot = display.newCircle( dial, 0, 145, 2.5 )
dial.dot:setFillColor( 255, 0, 0, 255 )
physics.addBody( dialcontainer.pivot, “static”, { friction=0, density=0, bounce=0 } )
physics.addBody( dial, “dynamic”, { friction=0, density=0, bounce=0, radius=150 } )

dialcontainer.pivotjoint = physics.newJoint( “pivot”, dialcontainer.pivot, dial, display.contentCenterX, display.contentCenterY )
function dragBody( event )
local body = event.target
local phase = event.phase
local stage = display.getCurrentStage()

if “began” == phase then
stage:setFocus( body, event.id )
body.isFocus = true

– Create a temporary touch joint and store it in the object for later reference
body.tempJoint = physics.newJoint( “touch”, body, event.x, event.y )

elseif body.isFocus then
if “moved” == phase then

– Update the joint to track the touch
body.tempJoint:setTarget( event.x, event.y )

elseif “ended” == phase or “cancelled” == phase then
stage:setFocus( body, nil )
body.isFocus = false

– Remove the joint when the touch ends
body.tempJoint:removeSelf()

end
end

– stop further propagation of touch event
return true
end

function moveBody( event )
if (event.numTaps == 1) then
dialcontainer.pivot.x, dialcontainer.pivot.y = event.x, event.y
dragBody( { phase=“began”, target=dial } )
dragBody( { phase=“ended”, target=dial } )
return true
end
end

dial:addEventListener( “touch”, dragBody )
Runtime:addEventListener( “tap”, moveBody )[/lua]

matt [import]uid: 8271 topic_id: 5373 reply_id: 17930[/import]

Hey Matt,

This is awesome. But I’m having trouble making these graphics instead of display.newCircle

Any ideas? [import]uid: 11144 topic_id: 5373 reply_id: 18596[/import]

I assume you mean using newImage instead of newCircle? Lets see your code… [import]uid: 8271 topic_id: 5373 reply_id: 18633[/import]

Actually, I figured it out last night. Frustrating, it was simple. I just forgot to add the parent group dial.

dial.wheel = display.newImage( dial, “newImageWheel” )

Once I did that, a few other tweaks, I got it working almost perfectly. Now I just need to get it to stop spinning forever with some physics.

Thanks for your code man. You saved me days! I’ll post credit in my code for you. Unfortunately, I work for a non-profit company, so I can’t credit you because we don’t do credits.
Thanks man!
[import]uid: 11144 topic_id: 5373 reply_id: 18810[/import]

Thanks for the credit, I do this cos I enjoy it.

If you apply angularDamping the dial should stop spinning on its own:

http://developer.anscamobile.com/reference/index/bodyangulardamping

You’ll need to play with it to work out the best effect.

m

Ps: Credit back if you can post your finished code - I’m sure there’ll be lots of people who will want the final thing. Including me. [import]uid: 8271 topic_id: 5373 reply_id: 18813[/import]

Here’s the code. Some of the images and stuff whoever’s looking at it won’t have, but if you replace the images, it should work.

Also includes part of the Director Class.

Side note, what this is is a wheel you spin, then on the outside of that wheel are other images that rotate around with it, that would show up in a box to the right. of the wheel. Mimics one of those old fashion wheels teachers use to use for grading if that makes any sense.

The wheel image is one image that has 5 sections to in in the image itself. Turn the wheel, lands on a particular segment, another image to the right of it shows up.

It’s not fully finished, but you get the main point here. Might be a bit sloppy, but it works.
Thanks again for your help.


module(…, package.seeall)

local director = require “director”

local physics = require( “physics” )
physics.start()
physics.setGravity( 1000, 1000 )
physics.setDrawMode( “normal” ) – normal, hybrid, debug

local centerX = display.contentCenterX
local centerY = display.contentCenterY
local localGroup
local makeButtons = function ()
–everything in here

----insert content windows–

local teenGospelscroll=display.newImage( “img/teen/teenGospelscroll.png” )
teenGospelscroll.x, teenGospelscroll.y=centerX, 0
teenGospelscroll.xScale, teenGospelscroll.yScale = .5,.5
localGroup:insert(teenGospelscroll)

local teenGodscroll=display.newImage( “img/teen/teenGodscroll.png” )
teenGodscroll.x, teenGodscroll.y= 70, -230
teenGodscroll.rotation = -72
teenGodscroll.xScale, teenGodscroll.yScale = .5,.5
localGroup:insert(teenGodscroll)

local teenCrossscroll=display.newImage( “img/teen/teenCrossscroll.png” )
teenCrossscroll.x, teenCrossscroll.y= -200, -150
teenCrossscroll.rotation = -144
teenCrossscroll.xScale, teenCrossscroll.yScale = .5,.5
localGroup:insert(teenCrossscroll)

local teenManscroll=display.newImage( “img/teen/teenManscroll.png” )
teenManscroll.x, teenManscroll.y= 100, 250
teenManscroll.rotation = -216
teenManscroll.xScale, teenManscroll.yScale = .5,.5
localGroup:insert(teenManscroll)

local teenTrustscroll=display.newImage( “img/teen/teenTrustscroll.png” )
teenTrustscroll.x, teenTrustscroll.y= 100, 250
teenTrustscroll.rotation = -288
teenTrustscroll.xScale, teenTrustscroll.yScale = .5,.5
localGroup:insert(teenTrustscroll)

–insert BackGround–
local teenBG=display.newImage( “img/teen/teenBG.png” )
teenBG.x, teenBG.y=centerX, centerY
teenBG.xScale, teenBG.yScale = 1,1
localGroup:insert(teenBG)

–[[
local wheel= display.newGroup()
wheel.xReference, wheel.yReference = 240, 160
–WHEEL–
local teenCross=display.newImage( “img/teen/teenCross.png” )
teenCross.x, teenCross.y=centerX, centerY
teenCross.xScale, teenCross.yScale = .5,.5

local teenGod=display.newImage( “img/teen/teenGod.png” )
teenGod.x, teenGod.y=centerX, centerY
teenGod.xScale, teenGod.yScale = .5,.5

local teenGospel=display.newImage( “img/teen/teenGospel.png” )
teenGospel.x, teenGospel.y=centerX, centerY
teenGospel.xScale, teenGospel.yScale = .5,.5

local teenMan=display.newImage( “img/teen/teenMan.png” )
teenMan.x, teenMan.y=centerX, centerY
teenMan.xScale, teenMan.yScale = .5,.5

local teenTrust=display.newImage( “img/teen/teenTrust.png” )
teenTrust.x, teenTrust.y=centerX, centerY
teenTrust.xScale, teenTrust.yScale = .5,.5

wheel:insert(teenCross)
wheel:insert(teenGod)
wheel:insert(teenGospel)
wheel:insert(teenMan)
wheel:insert(teenTrust)

localGroup:insert(wheel)
wheel.x = 140
]]


local dialcontainer = display.newGroup()
–dialcontainer.x, dialcontainer.y = -100, 0

dialcontainer.pivot = display.newCircle( dialcontainer, display.contentCenterX, display.contentCenterY, 10 )
dialcontainer.pivot:setFillColor( 0, 255, 100, 0 )

local dial = display.newGroup()
dialcontainer:insert( dial )
–dial:insert(wheel)

dial.x, dial.y = display.contentCenterX, display.contentCenterY

dial.wheel = display.newImage( dial, “img/teen/TeenWheel2.png” )
dial.wheel.x, dial.wheel.y=0, 0
dial.wheel.xScale, dial.wheel.yScale = .5,.5

dial:insert(teenGospelscroll)
dial:insert(teenGodscroll)
dial:insert(teenCrossscroll)
dial:insert(teenManscroll)
dial:insert(teenTrustscroll)
–add image content to here somewhere. Use “dial”

–display.newCircle( dial, 0, 0, 110 )
–dial.wheel:setFillColor( 0, 255, 100, 155 )
–[[
dial.dot =
–display.newImage( dial, “img/teen/teenPointer.png” )
display.newCircle( dial, 0, 105, 5 )
dial.dot:setFillColor( 0, 0, 0, 255 )
]]

physics.addBody( dialcontainer.pivot, “static”, { friction=1000000, density=1000000, bounce=1000 } )
physics.addBody( dial, “dynamic”, { friction=1000000, density=1000000, bounce=1000, radius=100 } )

dialcontainer.pivotjoint = physics.newJoint( “pivot”, dialcontainer.pivot, dial, display.contentCenterX, display.contentCenterY )


function dragBody( event )
local body = event.target
local phase = event.phase
local stage = display.getCurrentStage()

if “began” == phase then
stage:setFocus( body, event.id )
body.isFocus = true

– Create a temporary touch joint and store it in the object for later reference
body.tempJoint = physics.newJoint( “touch”, body, event.x, event.y )

elseif body.isFocus then
if “moved” == phase then

– Update the joint to track the touch
body.tempJoint:setTarget( event.x, event.y )

elseif “ended” == phase or “cancelled” == phase then
stage:setFocus( body, nil )
body.isFocus = false

– Remove the joint when the touch ends
body.tempJoint:removeSelf()

end
end

– stop further propagation of touch event
return true
end

function moveBody( event )
if (event.numTaps == 1) then
–dialcontainer.pivot.x, dialcontainer.pivot.y = event.x, event.y
dragBody( { phase=“began”, target=dial } )
dragBody( { phase=“ended”, target=dial } )
return true
end

end

dial:addEventListener( “touch”, dragBody )

–Runtime:addEventListener( “tap”, moveBody )

localGroup:insert(dialcontainer)
dialcontainer.pivot.x, dialcontainer.pivot.y = 140,centerY
local teenPointer=display.newImage( “img/teen/teenPointer.png” )
teenPointer.x, teenPointer.y=centerX-100, centerY
teenPointer.xScale, teenPointer.yScale = .5,.5
localGroup:insert(teenPointer)

return localGroup

end

new = function()
localGroup = display.newGroup()

makeButtons()

return localGroup
end [import]uid: 11144 topic_id: 5373 reply_id: 18834[/import]

Horaceburry,
Did you get your wheel to stop? I am currently starting a project that would be virtual wheel that will allow for custom text or images to be displayed as well as up to 36 different segments. I am trying to create an app that will allow a roulette style wheel like on the price is right or wheel of fortune. Do you have any ideas?
Thanks,
GDH [import]uid: 16179 topic_id: 5373 reply_id: 19475[/import]

To be frank, I’ve not tried - but if you take a look at post #5 you’ll see I mentioned angularDamping: https://developer.anscamobile.com/forum/2011/01/22/dial-not-behaving#comment-18813

Give that a shot and let us know what you find.

Of course, you could have a timer which waits for a second and measures the rate of spin (either rotate value over time or some angular momentum property) and just gradually decrease it. I think angularDampling would work best as I believe that will cause the spinning display object to come to a stop.

m [import]uid: 8271 topic_id: 5373 reply_id: 19476[/import]

Has anyone seen a code for a circular list like you would see in a recent call list or phone list but does not stop at the end or beginning of the list, but rather just appends the start to the end of the list and keeps going in either direction as apposed to stopping when the end or beginning of the list is reached. Is it possible to convert an existing list into a circular list?
Thanks,
GDH [import]uid: 16179 topic_id: 5373 reply_id: 19481[/import]

Off topic. You should start a new thread for that.

But, in answer to your question, (assuming you have a list which reaches off-screen) have an event listener for the enterFrame event which checks the y value (if you are scrolling up and down) of the top element of your table of display objects. I would use a table and not bother mucking about messing up the display group. Then, when the element at position 1 in the table goes off screen (y is less than 0 by half the element’s height) simply move it to the other end of the table and adjust it’s y value to visually move it there. Do the reverse when the y value of element 1 gets > 0. Basically, this is checking the position of the elements and shifting them in a list and on screen, when they are off screen. The check is done on element 1 because checking [1] and [x] is un-necessary.

m [import]uid: 8271 topic_id: 5373 reply_id: 19486[/import]