How to make an object slow down and stop ?

local ball2 = display.newCircle(150,400,20) physics.addBody(ball2,"dynamic") ball2:applyForce(100,-100,ball2.x,ball2.y) local function gameLoop() local vx,vy = ball2:getLinearVelocity() if (vx ~=0 or vy ~= 0) then vx = vx \* 0.6 vy = vy \* 0.6 ball2:setLinearVelocity(vx,vy) end end Runtime:addEventListener("enterFrame",gameLoop)

How to make an object slow down and stop ?

@martinlim520

I see some problems with your code and I’ll provide some answers too.  Bear with me:

Problems:

  1. Forces are not applied once.  You usually apply them every frame in an enterFrame listener. (If you’re looking for a ‘kick’ use and impulse instead, or set the linear velocity.
  2. Calling get/set linear velocity is OK in an enterFrame listener, but it may be a bit excessive and interfere with the natural/calculated behavior of the physics engine.  That said it is OK, just be careful.
  3. If you are setting velocities in ‘enterFrame’, at some point, the velocity will be so low it will essentially be zero.  You should set a cut-off point and manually treat values below that (absolute) value as zero.
  4. In none of your calculations are you taking into account mass.  This will  be fine unless you decide to make a physics object bigger or smaller, then all your hard work will go out the window because the objects will behave differently.  I always multiply forces by the objects’ masses (obj.mass) to get consistent behavior even if I later change the size of an object.

Answers:

  1. Your code is pretty good, but could be improved as noted above (I’ll show an improvement in a moment).
  2. The easiest way to slow an object down is via linearDamping.

Suggestion:

local ball2 = display.newCircle(150,400,20) physics.addBody(ball2,"dynamic") ball2.linearDamping = 0.5 -- make higher to slow down faster ball2:applyLinearImpulse(10 \* ball2.mass, -10 \* ball2.mass, ball2.x,ball2.y) -- or maybe something like this: --ball:setLinearVelocity( 100, -100 ) local function gameLoop() local vx,vy = ball2:getLinearVelocity() if( vx == 0 and vy == 0) then return end vx = (math.abs(vx) \< 0.005) and 0 or (vx \* 0.6) vy = (math.abs(vy) \< 0.005) and 0 or (vy \* 0.6) ball2:setLinearVelocity(vx,vy) end Runtime:addEventListener("enterFrame", gameLoop )

@martinlim520

I see some problems with your code and I’ll provide some answers too.  Bear with me:

Problems:

  1. Forces are not applied once.  You usually apply them every frame in an enterFrame listener. (If you’re looking for a ‘kick’ use and impulse instead, or set the linear velocity.
  2. Calling get/set linear velocity is OK in an enterFrame listener, but it may be a bit excessive and interfere with the natural/calculated behavior of the physics engine.  That said it is OK, just be careful.
  3. If you are setting velocities in ‘enterFrame’, at some point, the velocity will be so low it will essentially be zero.  You should set a cut-off point and manually treat values below that (absolute) value as zero.
  4. In none of your calculations are you taking into account mass.  This will  be fine unless you decide to make a physics object bigger or smaller, then all your hard work will go out the window because the objects will behave differently.  I always multiply forces by the objects’ masses (obj.mass) to get consistent behavior even if I later change the size of an object.

Answers:

  1. Your code is pretty good, but could be improved as noted above (I’ll show an improvement in a moment).
  2. The easiest way to slow an object down is via linearDamping.

Suggestion:

local ball2 = display.newCircle(150,400,20) physics.addBody(ball2,"dynamic") ball2.linearDamping = 0.5 -- make higher to slow down faster ball2:applyLinearImpulse(10 \* ball2.mass, -10 \* ball2.mass, ball2.x,ball2.y) -- or maybe something like this: --ball:setLinearVelocity( 100, -100 ) local function gameLoop() local vx,vy = ball2:getLinearVelocity() if( vx == 0 and vy == 0) then return end vx = (math.abs(vx) \< 0.005) and 0 or (vx \* 0.6) vy = (math.abs(vy) \< 0.005) and 0 or (vy \* 0.6) ball2:setLinearVelocity(vx,vy) end Runtime:addEventListener("enterFrame", gameLoop )