Kinematic collision object for the player character
Static collision for platform tiles
The player can jump and walk
Both player’s sprite and tiles don’t have any scaling: they are 16x16 pixels
When the player jumps, the gravity of 250 makes it slightly penetrate into tiles. So, for correction I tried using the approach given in the tutorials, including the code example by @britzl referred in another thread on the forum (Directional collision for platform jumping )
But very often (like 50% cases) the player object either gets stuck slightly jittering in the tiles, penetrating about half a pixel in them. Reducing the gravity from 250 to ~ 25 helps, but that looks like the object is falling underwater.
The best result so far was to dramatically simplify the penetration correction, and use rounding to the nearest larger integer:
local correction = collision.normal * math.ceil(collision.distance)
go.set_position(go.get_position() + correction)
The side effect is that sometimes the player object “hovers” one pixel above the visual tiles, slowly descending when the rounding somehow corrects itself.
Hmm, this is strange. I wonder if you’d get better results if you modify the physics scale in game.project (from the manual: “How to scale the physics worlds in relation to the game world for numerical precision, 0.01–1. The value is 0.02 by default.”)
Also, to make the testing more “visual”, I attached the camera to the game object, so if the collision object starts jittering against one another, the entire screen goes blurry (interesting effect).
Ok, so I’m guessing the problem is caused by multiple contact_point_response messages per frame that when dealt with one by one causes the jitter.
In the Getting Started Tutorial and in my platformer module this is dealt with by keeping track of the accumulated correction during the frame and using that to adjust the velocity.
Thanks @britzl ! I went through the code once again, and made sure that the correction is completely the same as in your samples. Especially:
Correction is accumulated
Correction is reset to (0, 0, 0) on each update call
Now it works.
However, I am still puzzled - why. The correction is still applied on every contact_point_response message, so if there are multiple messages coming over one frame, shouldn’t it still over-compensate? I see that somehow it works properly, though.
[UPD] All right, for those stumbled the same way I did, now I get it. Two lines below are the key: proj denotes how much of the compensation needed for this contact point was already covered during the frame, and only compensating for the difference (if any) then storing it in the correction vector for the frame.
local proj = vmath.dot(self.correction, normal)
local comp = (distance - proj ) * normal
self.correction = self.correction + comp