How to handle collision resolution when the normal is perpendicular to velocity

I’m having an issue where a kinematic object is traveling along the x axis and collides with a static object. When using the “translate the object along the normal amount” method (showcased in the platformer tutorial and the runner tutorial) the kinematic object shifts above the static object and continues traveling along the x axis. What I would like instead is to have the object halt its travel along the x axis and be shifted back along that axis so that it is no longer colliding with the object.

Here’s my understanding of what is happening, and the various methods I have attempted to work around this. My main question is: Is there a simple, robust solution to handling collisions when the normal is perpendicular to the velocity that shifts the object back along the axis from which it came?

Here’s an image I made of the scenario, and the collision data provided in the collision message.

The bottom left box is the kinematic object, the top right is the static object.
The arrows are the normals for each object, if it were to interpret the collision (so for our scenario, we only care about the yellow arrow)
The red dot is the position of the collision.

Because collisions are velocity agnostic, any time the kinematic square ends up in this collision, the result will be the same. If we were to be coming from below with a positive y velocity, then the normal would be exactly what we want. But in the case where we are coming from the left with a positive x velocity, the normal spits us out below the object and sends us on our way.

I looked into the box2d documentation, and according to my understanding of that this scenario occurs because either normal can be used as a means to escape the collision, so it chooses, in the case they are equal, arbitrarily (for the sake of this example - there is a method to it but it doesn’t help us). Otherwise, it chooses the normal that provides the least “effort” (in this case, distance) to escape the collision. So if we were to shift the the kinematic object 1 pixel “down”, then the normal would be trying to shove it down because that is the shortest distance out of the collision (4 pixels, instead of 5 to go to the left). so this can occur in scenarios where there is a sort of “grazing” collision.

I was hoping to be able to use the collision position to determine where to relocate the kinematic object to, unfortunately it seems to be based off of the normal axis (halfway between each object on the normal axis), and then off of the edge of one of the objects. From what I can tell, it is based off of whichever object is the “intruder” so to speak, although I’m not sure how it determines that yet. Unfortunately, that tends to mean the kinematic object, so I can’t be sure how far in it has penetrated the static object. If there is a connection or bit of info here that I could use, I’d be happy to know about it.

Another idea I had tried was to get a reference to the collision object with which the kinematic object is colliding, unfortunately it does not provide any information about its size or bounds. Perhaps there is a way to reference the collision shapes within it, but I haven’t yet found out how.

In light of not being able to reference the collision object, I looked into creating an invisible sprite for each object that shared bounds with the collision object. Sprites’ size can be accessed, so it seemed like a possible workaround. However, it seems that sprites inherit their size from the image they use, so I would need to create an empty image for every different game object instead of being able to define the boundaries in code. This also seems exceptionally hacky.

I believe that is the gist of the solutions I’ve tried. I believe I could do some manual script creation where each object has a script that just sets properties about its width and height (which is not much more effort than the sprite solution), however this seems excessive to deal with what seems like a somewhat common issue.

Without being able to figure out where the boundary of the static object is when responding to the collision in the kinematic object’s script, I’m thinking there isn’t a convenient and simple solution. I’m new to Defold and game development, so I’m hoping this is something simple other people have encountered and know the solution to - my searches in the forums didn’t turn anything up though.

Thank you in advance for anyone that can shed any light on my problem!

Hmm, I would have expected the behaviour to be that what you describe, ie that the object halts. Would you mind creating a minimal example of when this isn’t working so that I can take a look and better understand the problem (I think I understand it from you post, I just want to be sure).

Absolutely - here’s a basic example that has a kinematic square and two static squares. Git Repository. If you run it as is, and press the left arrow key you’ll see the kinematic square get pushed to below the static square, despite having a sizeable area of impact. This is (I think) because the “move-left” pushes it 10 pixels to the left, and it’s starting position places it at only 9 pixels into the object in the y axis, so the normal says “hey this is easier” and shoves it that way.

If you would like to see another scenario, change the static_2 object to be at (500, 470, 0) and watch the kinematic object bounce between the two indefinitely.

Thanks for helping me with this - it’s possible I’m missing something obvious, which I hope is the case!

[Note: the code has a lot of commented out print statements that you can use to see the values of various things at the time of impact.]

IMO, no matter how hard you try, resolving kinematic collisions with contact_point_response will not give you results you desire. Things would be even worse when you start thinking about movable platforms, pushable boxes and its combination. This is road to nowhere.
Use ray casts instead.

Thank you, dmitriy! I’m new to all this, so I’m just going with what I have until it stops working. I’ll look into using raycasting! Much appreciated : )