I'm using masks to make collision detection in a game using pygame. The detection works well, but I have had problems with the behaviour after collision.

In most games, the obstacles are vertical or horizontal, making easy manipulate the velocity of objects moving. So, if the object collide, there is just two options: cancel x component or cancel y component. In this way, the object stop the move only in the normal direction.

But, my obstacles have any shape (not any, just rectangles and triangles) and direction, making things hard.

Basically, I want to cancel the velocity component in the normal direction to obstacle in the collision point.

Some help?


  • 1
    \$\begingroup\$ I experimented with pixel-perfect terrain (similar to the Worms games) once and figured out a solution. However, it is rather complex and I'm not sure if it's really good, so I hesitate to post it as an answer. I more or less followed the tips that you can find in this article under the "Slopes" paragraph. \$\endgroup\$ – skrx Mar 11 '18 at 17:42
  • \$\begingroup\$ Could you tell me about this other solution? Any idea is welcome :) \$\endgroup\$ – CFLS Mar 12 '18 at 15:20

So it appears as you are actually asking how to find the normal on an arbitrary pixel mask, this is actually simple.

One method you might think of using, is to simply use the pixel mask pixel as a AABB collision. This can work, but has the unfortunate problem of potentially stoping your character from moving. If it is coarse enough though, you can merely treat it the same as you would with colliding against your boxes.

enter image description here

But you will run into issues where you collided and you get this result:

enter image description here

when what you probably wanted was this:

enter image description here

To solve this you need to use the pixel neighborhood in order to figure out the real "surface". for the intersected pixel, check the surrounding neighbor intersecting pixel, find the pixel which is the closest in direction to the colliding object impact direction vector (the negative of its velocity vector) and use the line created by these two points as the plane to create the normal from. To find out the normal for a line segment via the formula found here. Using this we can use the normal. here is a picture of what I'm talking about:

enter image description here

To use the normal, you will want to calculate the impulse on your colliding objects velocity with the surface normal, which will allow you to remove the part of your velocity which is normal to the surface.

  • \$\begingroup\$ I ended using rects for collisions and redesigning some obstacles. But, your answer is interesting and seems to be very good. It is very useful and I will use it soon. Thanks =D \$\endgroup\$ – CFLS Mar 31 '18 at 0:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.