2D Platformer Jittering & Coding Collision Handler

Hi, sorry if i’m writing this in bullet points instead of usual ‘human-like’ paragraph (cuz i don’t really know how to deliver my message best). Anyway, here, we go.

Problem:

  • Player jitters when ‘getting into’/moving into corners.
  • Player can jump from the wall (basically, doing wall jump). (no, i don’t want this feature)
  • Tunneling when jumping from a really high place

What i’ve tried:

  • Checking the documentation on ( Resolving kinematic collision in Defold ) ← i started out with this, ( Platformer Defold Tutorial ) ← I tried upgrading into this (i assume this cover for slope?).
  • Tried playing this ( Github | pixel-line-platformer-defold) and saw the player.script within (i assume this doesn’t cover for slope?).
  • Looking into this ( From jittery to smooth: A practical guide for physics games ) but, i assume this is mostly for dynamic-heavy physics?

What I want:

  • Just to fix the corner jitter, wall jump and tunneling

Current game state

  • Just a protoype, pretty much just beginning doing things
  • Plan on heavy bullet hell platformer (not too fast, and parryable by player)
  • May not even release this game, just wanna practice

What must be kept:

  • The keyboard inside my input has no ‘action.pressed’ (intentional), cuz i want continous jumping while it is being held down.
  • Speed & gravity (yes, the platformer i planned on is something like a bullet-hell combination with high-speed movement)
  • (optional) Although my game won’t be introducing slopes currently, I want my collision handler able to handle slopes (for future games)

Additional notes:

  • No, i don’t use AI to write this forum (if you care) however, i do refer to Gemini to help resolving the problem, and no, the problem still persists.
  • I’m not really a super-beginner (somewhat intermediate) , just never really make my own ‘first game’
  • I came from Love2D background with a little bit of Unity (this was about 2 years ago, so yeah, you guys can ignore this)

Technical notes (refer gamefile):

  • I have “fall_vel_cap” to prevent vertical tunneling, but it doesn’t work?
  • I thought about putting NORMAL_JITTER_TRESHOLD thinking it would fix the jitter by “refixing” the normal into a 0 and avoid floating value (snap into pure x/y-axis). (referenced from pixel-line-platformer) but I think this would prevent slope handling latter in the future.
  • I tried updating go.set_position both in update(+ velocity) and on_message(+ self.correction). I assume this would be correct since other example just update the GO position within on_message? Idk if i should change into fixed update or anything?
  • I did tilemap collision refering to this ( Tilemap Collision | Defold)

My Game:

What I plan on doing:

Anyway, thank you for reading, and any comment or help is welcome. (Not sure if I got the time to instantly reply tho)

* the forum limit the link only for 5, so, just assume the thin inside parenthesis was the topic i searched on Defold’s official documentation.

UPDATE:

  • RaycastLearning.zip (82.9 KB) I followed Sebastian Lague code of Unity’s kinematic platformer. And at “most basic” this is the result i got (which, im SUPER satisfied with as it can handle bullet speed).
    Note that I separate player’s control (player.script) away from raycast handling (utils/controller_2d.lua). The collision of my tilemap(and tilesource) are both grouped as “solid”. With my player hitbox grouped as “player” (not really needed tho, cuz raycast was the one handling the collision).
    I’ll just leave this .zip here for any beginner(including myself) wanting to learn raycast collision with Defold API. Also, this basic code is only basic at most, so, don’t expect any moving platform or slope handling.
    And, if you’re wondering, yes, I used AI (for anyone’s concern) to code this one(with some adjustment and tinkering). So if any of you don’t get what a certain line does, just ask AI. I’m too lazy to put detailed comments.
    Well, all in all, feel free to refer this basic starting code of mine. If you want something advance, I recommend checking out “Defold’s Platypus”.
  • I tried doing this “high-speed” platformer test with dynamic body for the player, and adjusting it’s velocity. But, even after adjusting the body’s restitution, mass, and game.project’s gravity; the player keep on “jitter bouncing”.
    I assume it has something to do with how I setup the tilemap’s collision? (It’s grid-based, although, not that I know if tilemap hitboxes get stitched together)
  • Do check out this forum (Discussion: Ideal Collision Algorithm), as the idea of Parallelogram Raycasting sounded very robust.

That’s fairly easy - divide tiles to “ground” and “wall” groups and reset your “self.is_grounded” flag only in response to ground.

I took a look at your project. Is there a specific reason you’re using kinematic collisions with manually simulated gravity? It might actually be easier to achieve everything you need by using dynamic physics instead.

If you want to stick with kinematic collisions, I’d recommend moving your movement logic to fixed_update() instead of update(). That said, I don’t think this alone will solve all (or any right away) of the issues you’re experiencing, but may give you more predictable results.

As for raycasts, they could be a very good solution and they’re not that difficult to implement. The basic idea is to cast a ray from the player’s current position to the position where you intend to move them. If the ray doesn’t hit anything, you can safely move the player there.

If the ray does hit something, use the hit point (offseted by half of the player’s width) to calculate the closest valid position. This lets you place the player right next to the obstacle without penetrating it, which also helps prevent tunneling at high speeds. I would start with one ray cast to the left, one to the right and one to the bottom.

2 Likes

Neato. :ok_hand:

Separating the tiles into 2 groups worked. However, it i were to add a tile like a box or non-wall obstacle, the wall jump behavior was still there. So when i to added a box i can’t just tag the box as ‘wall’ or ‘ground’.

As for not using dynamic physics, I heard some articles/forums (not limited to Defold) saying it’s not good practice as dynamic physics can be somewhat ‘floaty’ or ‘unresponsive’ especially in high body count.

HOWEVER, that’s not the reason for me not using it. I just simply wanted to code/learn the collision behavior like AABB or raycast thingy manually, that’s all. So, nothing biased.

Anyway, as for now I’ll try doing a raycast I guess. And, while at it I’ll try testing doing platformer using Dynamic body (which, I assume I need to ‘set’ some properties to 0).

Thanks for the reply, the separation of wall to ground does help quite a bit.

1 Like

It’s true that kinematic physics gives you much more control, but with the right setup, dynamic physics can be very flexible as well.

Regarding the wall/ground issue, I personally don’t like using tile-based collisions directly. I usually use the tilemap only for rendering, while the actual collision geometry consists of separate collision shapes. This not only reduces the number of colliders. For example, a whole row of tiles can be represented by a single box. It also gives you more control over collision behavior - for instance, you can assign different collision groups to different parts of the level, treating the top of a platform as ground while its sides are treated as walls. Downside is ofc a bit more work…

Another option is to reset self.is_grounded only when you stop colliding with a surface whose collision normal points upward. That way, touching a wall won’t cause the player to lose their grounded state.