You cannot move physics bodies by changing their screen position (x and y values) because you are “fighting the physics engine”. The engine is trying to position the bodies (and with them their display object) as determined by their weight, density and various velocities. Don’t do it.
You are correct in that you should be trying to move your body with setLinearVelocity() but, of course, you also want to control it’s position absolutely. Linear and Angular velocity get a body moving, literally, but they’re not good for fine control.
To absolutely position a body you either need it to be static and use it’s .x and .y values (the ONLY time you can do this) or when it is dynamic or kinematic use a touch joint and use the joint’s setTarget() function. Like this…
local rect = display.newRect( 200, 200, 100, 100 ) physics.addBody( rect, "dynamic" ) local touchjoint = physics.newJoint( "touch", rect, rect.x, rect.y ) touchjoint:setTarget( 300, 200 )
The code above creates a square at (200,200), makes it a physics body and then moves it to (300,200).
You will occasionally notice that physics bodies will start to spin or have a bit of wobble when you do this. To counteract this you can give them linearDamping or angularDamping. You might even want to only apply the damping when the body is NOT being moved, because damping is a mechanism used to consume the velocity of the body - with the effect of slowing the body down, like it’s in glue or mud.
Another technique to avoid spin is to set the .isFixedRotation=true property of the body, but be careful - if you create a weld joint on the body and you cannot have .isFixedRotation set to true. They just don’t work together. Basically, the weld joint won’t work and the body will just drop.
A bit of a trick for physics bodies - and this is a cheat with negative side-effects - is to switch the physics body off, move it as a display object and then turn the body back on. Simply set the .isBodyActive=false, move the object and then set .isBodyActive=true again. Of course, the body will not interact with any other physics objects while turned off, so you probably want to avoid this.
The final technique you can use to absolutely position a physics body without messing around with potentially imprecise methods is to create an invisible, static sensor body at the same location as the body you want to control. Weld the dynamic body to the static sensor body and then just absolutely position the static body with it’s .x and .y values. This is a massive cheat but does work, like this…
local rect = display.newRect( 200, 200, 100, 100 ) physics.addBody( rect, "dynamic" ) local anchor = display.newCircle( rect.x, rect.y, 5 ) physics.addBody( anchor, "static", { isSensor=true, radius=5 } ) local weldjoint = physics.newJoint( "weld", anchor, rect, rect.x, rect.y ) anchor.x = 300
A word of warning on this one - I have seen it go wrong some time ago but not for a while. The objects which were welded together simply disappeared but appeared to be still in the physics world.