In this post tepples mentioned he was looking for an efficient way to test this kind of collision, and then UncleSporky thought this was worth discussing, so I made this topic to share my findings in this area.
Games objects usually collide with everything else in the game (other objects and surfaces) through the use of a bounding box that represents its solid area. However, when you respect the object's bounding box and put it on a slope, it doesn't look very good:
The object will appear to be standing on air rather than on the ground. Some games compensate that with art, by drawing the ground above the logical collision surface:
This solution is quick but will probably make the levels hard to edit since the art is so different from the collision data. Also, it's not an optimal solution because depending on how wide the objects are they will still look like they are floating (too wide) or sunk into the floor (too narrow):
To fix this, the best solution I found was to use a central point (or a small segment between two points, but one point is simpler and appears to work OK) for collision with the ground:
Now the width of the bounding boxes don't matter, all objects will be adequately positioned on the floor. There is one big problem though: here's what happens when the object walks off a ledge:
Yup, it will fall while half of its body is stuck into the wall. Not good, huh? So you either let that ugly side effect happen or you suddenly push the object away from the wall to fix it, causing jerky movement. Both options suck, so I came up with a 3rd one: When the central point (or line) is not making contact with the floor, then you use the corners of the bounding box to check for collisions:
But the secret is to not allow the bounding box's corners to collide with slopes, they only collide with completely solid blocks (while the central point collides with solid blocks AND slopes). In the image above, it's like the slope has "guided" the game object to land on the solid block, and then it's like the slope doesn't exist anymore, because there's nothing below the central point. If the object keeps moving left, it'll eventually fall, but it won't be stuck into the wall.
To me it seems like this would work perfectly for all kinds of games. There are a few limitations though. For example, the slopes have to start and end connected to solid blocks. I mean, you can't use the side of a slope as a wall, because things like this would happen:
You can't have the end of a slope leading to nowhere like that. If you want your slope to lead to a pit, you have to add some "trimming". Something like this would do the trick:
All sorts of crazy slopes will work fine, as long as long as the complex shapes start and end on solid blocks. I like to think of the slopes as "decoration", something that makes the otherwise blocky areas more interesting, but the basic shape of the levels is still made of solid blocks:
I tried looking for existing games that behave like what I just described and the closest thing I found was Mega Man X (SNES). It doesn't have many slopes, and I have no idea of how they are actually implemented, but all the features and limitations I mentioned here seem to apply: After going down a slope that leads to a pit, Mega Man will move horizontally for a few pixels, like he was standing on a flat block, before falling (that's the "objects don't get stuck in the wall" feature). All the rising slopes that lead to pits I could find in that game have a flat area before the pit (that's the "the sides of slopes can't be used as walls" limitation).
Even if this isn't exactly what Mega Man X or any other game does, I still think it's a pretty good solution. I don't think the few limitations are deal breakers by any means, and the whole idea seems very simple to me, and easy to implement on top of an already working "bounding box to solid blocks" solution. Nothing about a working engine like that would have to be changed, only a new collision point and a new type of block (a block with a height map) would have to be added.
Please let me know what everyone thinks, if you have suggestions on how to improve this idea or if you can see potential problems I might have overlooked.
Games objects usually collide with everything else in the game (other objects and surfaces) through the use of a bounding box that represents its solid area. However, when you respect the object's bounding box and put it on a slope, it doesn't look very good:
The object will appear to be standing on air rather than on the ground. Some games compensate that with art, by drawing the ground above the logical collision surface:
This solution is quick but will probably make the levels hard to edit since the art is so different from the collision data. Also, it's not an optimal solution because depending on how wide the objects are they will still look like they are floating (too wide) or sunk into the floor (too narrow):
To fix this, the best solution I found was to use a central point (or a small segment between two points, but one point is simpler and appears to work OK) for collision with the ground:
Now the width of the bounding boxes don't matter, all objects will be adequately positioned on the floor. There is one big problem though: here's what happens when the object walks off a ledge:
Yup, it will fall while half of its body is stuck into the wall. Not good, huh? So you either let that ugly side effect happen or you suddenly push the object away from the wall to fix it, causing jerky movement. Both options suck, so I came up with a 3rd one: When the central point (or line) is not making contact with the floor, then you use the corners of the bounding box to check for collisions:
But the secret is to not allow the bounding box's corners to collide with slopes, they only collide with completely solid blocks (while the central point collides with solid blocks AND slopes). In the image above, it's like the slope has "guided" the game object to land on the solid block, and then it's like the slope doesn't exist anymore, because there's nothing below the central point. If the object keeps moving left, it'll eventually fall, but it won't be stuck into the wall.
To me it seems like this would work perfectly for all kinds of games. There are a few limitations though. For example, the slopes have to start and end connected to solid blocks. I mean, you can't use the side of a slope as a wall, because things like this would happen:
You can't have the end of a slope leading to nowhere like that. If you want your slope to lead to a pit, you have to add some "trimming". Something like this would do the trick:
All sorts of crazy slopes will work fine, as long as long as the complex shapes start and end on solid blocks. I like to think of the slopes as "decoration", something that makes the otherwise blocky areas more interesting, but the basic shape of the levels is still made of solid blocks:
I tried looking for existing games that behave like what I just described and the closest thing I found was Mega Man X (SNES). It doesn't have many slopes, and I have no idea of how they are actually implemented, but all the features and limitations I mentioned here seem to apply: After going down a slope that leads to a pit, Mega Man will move horizontally for a few pixels, like he was standing on a flat block, before falling (that's the "objects don't get stuck in the wall" feature). All the rising slopes that lead to pits I could find in that game have a flat area before the pit (that's the "the sides of slopes can't be used as walls" limitation).
Even if this isn't exactly what Mega Man X or any other game does, I still think it's a pretty good solution. I don't think the few limitations are deal breakers by any means, and the whole idea seems very simple to me, and easy to implement on top of an already working "bounding box to solid blocks" solution. Nothing about a working engine like that would have to be changed, only a new collision point and a new type of block (a block with a height map) would have to be added.
Please let me know what everyone thinks, if you have suggestions on how to improve this idea or if you can see potential problems I might have overlooked.