how to decelerate smoothly to a target point?

I’ve got a sample below with basic horizontal movement implemented by tapping/holding on the screen, then using applyForce in the appropriate direction. What I would like to do is this: when the user releases touching the screen, set the next ground square (in the direction the mover is moving) as the destination, and have the moving object decelerate smoothly until it lands squarely on the destination tile.

I’m wondering if it would be some kind of combination of the physics motion and an animation, or if I just have to do the math to figure out the deceleration and use setLinearVelocty. I was thinking it might look jerky in the transition from just letting the physics control the velocity to using an animation. I haven’t tried an easing function either, not sure how they work.

The elevator in Tiny Tower would be a vertical example close to what I’m looking for. There’s still the awkward case where the natural velocity takes the moving object just past a ‘landing’ area of one target area, but hopefully I can get the general case figured out first.

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

physics.start()
physics.setDrawMode( “hybrid” )

display.setStatusBar (display.HiddenStatusBar)

– copied this game/displayGroup usage from EggBreaker sample physics code
local game = display.newGroup()

– copied from Slideview example; background used to handle screen touches below
local screenW, screenH = display.contentWidth, display.contentHeight
local background = display.newRect( 0, 0, screenW, screenH )
background:setFillColor(0, 0, 0)
game:insert(background)

----- make ‘ground’ tiles ------
local tileWidth = 60
local tileHeight = 60

for col = 0, 5 do
groundTile = display.newRect( (col*tileWidth), 180, tileWidth, tileHeight)
physics.addBody( groundTile, “static”, { density=3.0, friction=0.5, bounce=0.2 } )
end
local mover = display.newRect( 120, 130, 55, 55)
physics.addBody( mover, { density=3.0, friction=0.5, bounce=0.2 } )
function mover:enterFrame (event)
if( _G.holdingRight ) then
mover:applyForce( 150, 0, mover.x, mover.y )
end
if( _G.holdingLeft ) then
mover:applyForce( -150, 0, mover.x, mover.y )
end
end

Runtime:addEventListener(“enterFrame”, mover)


– move via screen touches –

local function checkTouchDirection(event)
local difY = math.abs(event.y - mover.y)
local difX = math.abs(event.x - mover.x)

if((event.x < mover.x) and (difX > difY )) then
_G.holdingLeft = true
else
_G.holdingLeft = false
end

if((event.x > mover.x) and (difX > difY )) then
_G.holdingRight = true
else
_G.holdingRight = false
end
end

local function screenTouched(event)
local touchFocus = event.target

local phase = event.phase
if( “began” == phase ) then
display.getCurrentStage():setFocus( touchFocus )
touchFocus.isFocus = true
checkTouchDirection(event)
elseif “moved” == phase then
checkTouchDirection(event)
elseif “ended” == phase or “cancelled” == phase then
display.getCurrentStage():setFocus( nil )
touchFocus.isFocus = false
_G.holdingLeft = false
_G.holdingRight = false
end
return true
end

background:addEventListener( “touch”, screenTouched )

transition.to with the easing option is really useful. Try:

transition.to ([image/sprite], {time=1000, x=[end_horiz], y=[end_vert], transition=easing.outExpo, onComplete=[where_next]})

time=1000 is 1 second.

Between contentWidth/Height, and setReferencePoint, you can be really particular about where it finishes.

In terms of easing,you can use in/out/inOut with Expo or Quad. “outExpo” will give you a fast movement, with a ‘hard brake’ at the end. Experiment! [import]uid: 82595 topic_id: 20849 reply_id: 84238[/import]