Pushing object at constant velocity

Hey guys,

I have a physics object that I would like to have move at a specific set speed and never go faster or slower.  I currently am using applyForce every frame and checking the objects velocity before applying more force.

Just wondering if others have ideas of a better way to do this, or is this the best option?  Another option might be to use the “setVelocity” method to keep it at a constant speed.

Any suggestions or comments are appreciated.  Wanted to ask becasue this will be the core of my game.

Well, in physics (not just the physics engine, but in real-world physics), when you apply a force to a body, it accelerates.  (Force = mass x acceleration, so acceleration = Force / mass).  If you keep applying a force, it’ll keep accelerating.  After you’ve stopped applying a force, it’ll continue moving at the same velocity (inertia) until it encounters another force, which might be a wall, another object, or, importantly, friction.

In the physics engine, there’s a form of friction that’s simulated by the linearDamping property.  If you have that property set above 0, then objects won’t maintain a constant velocity as they move through space.  They’ll slow down over time, as if there were air resistance.  Thus, with linearDamping>0, you’d have to continue to apply a force to keep the object moving at the same speed, to counteract the damping force of friction.  (Note, what I’m describing here is different from the actual “friction” property of a physics object, which has to do with when it’s colliding with another object.)

To get an object to move at a constant velocity, you could just apply a force one time, or set it’s velocity one time, and then just make sure linearDamping is zero.

  • Andrew

Andrew,

Thank you very much for the response, those are some very good points.  I will try what you suggest and report back. sounds like it should work out great!

Well, in physics (not just the physics engine, but in real-world physics), when you apply a force to a body, it accelerates.  (Force = mass x acceleration, so acceleration = Force / mass).  If you keep applying a force, it’ll keep accelerating.  After you’ve stopped applying a force, it’ll continue moving at the same velocity (inertia) until it encounters another force, which might be a wall, another object, or, importantly, friction.

In the physics engine, there’s a form of friction that’s simulated by the linearDamping property.  If you have that property set above 0, then objects won’t maintain a constant velocity as they move through space.  They’ll slow down over time, as if there were air resistance.  Thus, with linearDamping>0, you’d have to continue to apply a force to keep the object moving at the same speed, to counteract the damping force of friction.  (Note, what I’m describing here is different from the actual “friction” property of a physics object, which has to do with when it’s colliding with another object.)

To get an object to move at a constant velocity, you could just apply a force one time, or set it’s velocity one time, and then just make sure linearDamping is zero.

  • Andrew

Andrew,

Thank you very much for the response, those are some very good points.  I will try what you suggest and report back. sounds like it should work out great!

Here is an example of a ball moving at constant speed:

[lua]

local function moveBall()

        physics.setGravity( 0, 0 )

        ball.object.gravityScale = 0

        ball.object.linearDamping = 0

        local x = math.random( -30, 30 )

        local y = math.random( -30, 30 )

        ball.object:applyForce( x, y, ball.object.x, ball.object.y )

end

local function onBallCollision(self, event)

        if ( event.phase == “began” ) then

                print( self.colorIndex … " collision began with " … event.other.colorIndex )

        end

end

local bo = display.newCircle( _W / 2, _H / 2, ball.size )

bo:setFillColor( 0.5 )

sceneGroup:insert(bo)

–physics.addBody( bo, { density=1.0, friction=0.3, bounce=1, radius=ball.size - 5 } )

physics.addBody( bo, { density=0, friction=0, bounce=1, radius=ball.size } ) --edited

bo.colorIndex = 1

bo.collision = onBallCollision

bo:addEventListener( “collision”, bo )

moveBall()

[/lua]

The trick is to set gravity to 0,0 and ball bounce to 1, so that the ball with not loose its speed after collision.

Daniel

if you have a lot of bouncing/collision going on you might still drift off your fixed velocity just due to approximations in box2d (even with damping 0, bounce 1)  so depending on how nitpicky you are, you might need to manually correct it every so often

fe, pseudocode:

local vx,vy = body:getLinearVelocity() -- velocity components local v = math.sqrt(vx\*vx+vy\*vy) -- velocity magnitude -- print("velocity delta error = ", v-MAX\_VEL) -- optional for debugging local nx,ny = vx/v, vy/v -- normalized local sx,sy = nx\*MAX\_VEL,ny\*MAX\_VEL -- scaled to your constant body:setLinearVelocity(sx,sy) -- reset

Have you tried:  setLinearVelocity()?

I’m using it to move my enemies in a game right now at a fixed speed.

Yes, objects can move at a fixed speed using setLinearVelocity or applyForce

But, how to keep that constant speed after collision? I think density was my problem.

This works ok for the example I posted above:

[lua]

physics.addBody( bo, { density=0, friction=0, bounce=1, radius=ball.size } )

[/lua]

Daniel

You can add collision detection to your object and when you get a collision with an object apply new linearVelocity.  Since we don’t know what you’re trying to do, I’m going to make up an example.   Lets say you have two walls and you need to move an enemy between the two walls, simply setup a collision filter for the enemy and the walls.  When it collides, apply the opposite velocity and you can have an object move back and forth.

Rob

Thanks Rob. That’s a good approach. Apply force with density 0 and bounce 1 also works 4 me.

Daniel

Here is an example of a ball moving at constant speed:

[lua]

local function moveBall()

        physics.setGravity( 0, 0 )

        ball.object.gravityScale = 0

        ball.object.linearDamping = 0

        local x = math.random( -30, 30 )

        local y = math.random( -30, 30 )

        ball.object:applyForce( x, y, ball.object.x, ball.object.y )

end

local function onBallCollision(self, event)

        if ( event.phase == “began” ) then

                print( self.colorIndex … " collision began with " … event.other.colorIndex )

        end

end

local bo = display.newCircle( _W / 2, _H / 2, ball.size )

bo:setFillColor( 0.5 )

sceneGroup:insert(bo)

–physics.addBody( bo, { density=1.0, friction=0.3, bounce=1, radius=ball.size - 5 } )

physics.addBody( bo, { density=0, friction=0, bounce=1, radius=ball.size } ) --edited

bo.colorIndex = 1

bo.collision = onBallCollision

bo:addEventListener( “collision”, bo )

moveBall()

[/lua]

The trick is to set gravity to 0,0 and ball bounce to 1, so that the ball with not loose its speed after collision.

Daniel

if you have a lot of bouncing/collision going on you might still drift off your fixed velocity just due to approximations in box2d (even with damping 0, bounce 1)  so depending on how nitpicky you are, you might need to manually correct it every so often

fe, pseudocode:

local vx,vy = body:getLinearVelocity() -- velocity components local v = math.sqrt(vx\*vx+vy\*vy) -- velocity magnitude -- print("velocity delta error = ", v-MAX\_VEL) -- optional for debugging local nx,ny = vx/v, vy/v -- normalized local sx,sy = nx\*MAX\_VEL,ny\*MAX\_VEL -- scaled to your constant body:setLinearVelocity(sx,sy) -- reset

Have you tried:  setLinearVelocity()?

I’m using it to move my enemies in a game right now at a fixed speed.

Yes, objects can move at a fixed speed using setLinearVelocity or applyForce

But, how to keep that constant speed after collision? I think density was my problem.

This works ok for the example I posted above:

[lua]

physics.addBody( bo, { density=0, friction=0, bounce=1, radius=ball.size } )

[/lua]

Daniel

You can add collision detection to your object and when you get a collision with an object apply new linearVelocity.  Since we don’t know what you’re trying to do, I’m going to make up an example.   Lets say you have two walls and you need to move an enemy between the two walls, simply setup a collision filter for the enemy and the walls.  When it collides, apply the opposite velocity and you can have an object move back and forth.

Rob

Thanks Rob. That’s a good approach. Apply force with density 0 and bounce 1 also works 4 me.

Daniel