Cannot properly correct penetration during collisions

I have a basic platformer setup:

  • 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.

So what am I doing wrong?!

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.”)

Yep, I did experiment with this setting.

0.01 to 0.1 didn’t really improve anything, setting to above 0.1 made jittering only worse.

I uploaded the video with my simplified implementation of collision correction

[details=Summary]This text will be hidden[/details]https://forum.defold.com/uploads/default/original/2X/5/5b43a875e1fc7dfdd94cb2238937b1e828379e91.mov

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).

I have the same problem when collision type is Kinematic, but Dynamic is okay. No sure why…

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