How to implement a spinning arrow that slows down

Hi, I’m trying to implement a game that involves a spinner (such as one you’d find in Twister) that has an arrow that spins around and around and then slows down eventually to a stop.

Currently for the spinner I only use the rotate() function with a constant angle, and it gets repeated several times with timer.performWithDelay().  This is a very basic spinner but obviously not what I want, since it does not slow down.  Perhaps I can do the slowing down without physics but I’m not sure what would be the best approach.

I’ve been reading up the tutorial on the various physics joint types, but I’m not sure how to start.  Pivot joint?  Wheel joint?  Or weld joint?  Do I use angular damping?

Also, does the “rotation” value of the object get populated if you use a physics movement, just like when I used the rotate() function on the object without physics?

The two bodies involved:

  • the spinner background which is split up into 6 sections (like a pie), with each section showing a value. 

  • the spinner arrow itself, which is centered on top of the spinner background

Any help would be appreciated.  Thanks!

You could easily use a pivot joint and give it a motor and gradually reduce the speed of the motor.

I would probably avoid physics and have a table with a value which is decreased using a transition. An enterframe event could then be used to rotate the spinner each frame by the table value. This would be the most accurate way of specifying the completion time.

local spinner = display.newGroup() local line = display.newLine( spinner, 0,0 , 50,0 ) spinner.spinBy = 10 spinner.completionTime = 10 local function doSpin() spinner.rotation = spinner.rotation + spinner.spinBy end local function endSpin() Runtime:removeEventListener( "enterFrame", doSpin ) end transition.to( spinner, { time=spinner.completionTime, spinBy=0, onComplete=endSpin } ) Runtime:addEventListener( "enterFrame", doSpin )

Two ways in my mind:

  1. Use only one transition but use easing so that it slows down gradually near the end of the spin.

  2. Use an enterFrame function that does two things: firstly it rotates the arrow each frame by a “speed” value. Secondly it detracts an “acceleration” value from the “speed” value.

Thank you very much, both of you! I think a combination of both answers will work; that is, use a transition.to to gradually slow it down but use a specific easing property to make the slowdown non-linear.

You could easily use a pivot joint and give it a motor and gradually reduce the speed of the motor.

I would probably avoid physics and have a table with a value which is decreased using a transition. An enterframe event could then be used to rotate the spinner each frame by the table value. This would be the most accurate way of specifying the completion time.

local spinner = display.newGroup() local line = display.newLine( spinner, 0,0 , 50,0 ) spinner.spinBy = 10 spinner.completionTime = 10 local function doSpin() spinner.rotation = spinner.rotation + spinner.spinBy end local function endSpin() Runtime:removeEventListener( "enterFrame", doSpin ) end transition.to( spinner, { time=spinner.completionTime, spinBy=0, onComplete=endSpin } ) Runtime:addEventListener( "enterFrame", doSpin )

Two ways in my mind:

  1. Use only one transition but use easing so that it slows down gradually near the end of the spin.

  2. Use an enterFrame function that does two things: firstly it rotates the arrow each frame by a “speed” value. Secondly it detracts an “acceleration” value from the “speed” value.

Thank you very much, both of you! I think a combination of both answers will work; that is, use a transition.to to gradually slow it down but use a specific easing property to make the slowdown non-linear.