I just realized it is better to do vertical collision first, because vertically hitting a sloped platform does not effect horizontal movement, but moving horizontally along a sloped platform does effect vertical movement.
But then you'd have to compensate for getting kicked upwards before you're pushed back out of a wall, for one thing. I did horizontal first and basically just patched around normal collision on the frame that you land to preserve your speed and such. Seems like a substantial workaround either way.
Though it would probably help at higher speeds to do vertical first, when you have a problem with the horizontal sensor hitting the slope. I guess it depends heavily on the application. I dunno.
If floors and walls are the same thing then you'll have the issue either way, the only difference is which axis… although I never had to compensate in the first place. I think it has to do with the fact that only one axis has moved by the time the first check happens. This means that against a wall, when the vertical check happens you still aren't inside the wall (so no pushing back), and when the horizontal check happens you're already in the final vertical position.
Had another idea. Since a lot of code is spent fetching the tile number from the level map, and using it to look up the collision data, it would be easier and more efficient to have a scrolling collision map, and fetch collision data from there.
I doubt it honestly since most of the code will go in calculating the offset anyway. You could make it simpler by using a look-up table pointing to every row though (then you just fetch the row from there and add the offset within the row, avoiding shifts/multiplication in the first place). The scrolling collision map may still help to allow the map to be stored compressed in ROM though (you decompress the surrounding area in RAM and work on that, assuming the entire level itself wouldn't just fit completely for starters).
EDIT: also before I forget, doing the vertical check first isn't enough for slopes. Depending where you are, you could still not be pushed high enough to be moved into the above row, but then move horizontally far enough to move into the next column, and you'll end up hitting a wall there, causing you to stop. Whoops. The only quick workaround is to do the move/collision step for every pixel. Not as bad as it sounds since it's unlikely you'll be moving many pixels (e.g. in a platformer usually you won't be going faster than 2-3 pixels horizontally, and not that much faster vertically either, and the player would be the only object moving that fast that also requires accurate physics).
I would be able to access the collision data for every surrounding tile, without changing the X index register. I would need to double the collision data map, so it can wrap around.
Sik wrote:the player would be the only object moving that fast that also requires accurate physics.
In a platformer, sure. Bullets in a shooter are another case. (Of course, then you don't have to deal with ejection.)
Not necessarily. If a bullet collides with a wall in most shooters, the animation for the bullet "exploding" I guess, is usually displayed right outside the wall.
Yeah that's the thing, bullets don't need anywhere as accurate collision detection and response. In fact, the response is always the hardest part since it messes with the physics of the object in question - an object that doesn't need any proper response (such as a bullet, which would just instantaneously stop there) is much easier to program and also generally can have more sloppy detection in the first place.
There's also the fact that when a bullet collides you don't care if it's a handful of pixels too deep. A player or an enemy, on the other hand, need to be pixel-perfect, and even in this case there's some leeway (e.g. enemies usually ignore solid objects and they may treat slopes as surfaces they can't go through, much like a wall, as long as they fulfill their basic purpose).
I surely wouldn't waste time calculating bounding boxes for bullets, so I'd most likely treat them as points. I guess that would require a separate collision routine.
Even something as simplistic as Missile Command probably has several collision routines: missiles with the ground, missiles with explosions, and bomber planes or kill sats with explosions.
There are basically three classes of collision routine in my platform game:
1. Test a point against the tile grid and all movable objects (represented as a set of bounding boxes).
2. Test a point, and return a distance to eject in one direction. (There's four of these.)
3. Test two bounding boxes for overlap.
1 is useful for testing things irrelevant to motion. Is the player on the ground? Has a bullet or particle hit a wall?
2 is useful for motion. When you move something to the right, test a point for collision with the world, then return how many pixels you need to move to the left to eject from the thing you collided with. This interacts with other movable objects well, since if you're colliding with both a tile and a bounding box, you can simply return the maximum ejection distance. For most objects you need to test two or three points on the leading edge of the object (corners + however many interior points you need for coverage), and take the maximum ejection distance found.
3 is used for interaction between objects. When to hurt the player. When to trigger a response. This is the most common one, I think. Only some creatures in my game need to respond to walls like with 2, but they all need to respond to touching the player, pretty much.
I knew that tile collision was different than object collision, but I didn't know anyone programmed it 2 different algorithms for the same type of collision.