There was a remaining bug in my collision detection code that allowed an actor penetrate a corner no matter what I did. I was able to gloss over this when I just had one actor moving through a level. However, I thought it was something I'd need to fix in order to make collisions between multiple actors work better. Except I. Can't. Fix. The. Damn. Thing.
Having no way to tell where the bug could be coming from I'm just dumping my code here in the vague hope that someone else will bother to read it.
So you know what you're getting into:
- I use a predictive approach to collision detection
- I test if and when a collision will occur before moving an actor
- The player-controlled actor is a circle
- Walls are represented by edge line segments and corner points
- When moving an actor, I get the line segments and corner points the actor will likely hit
- I test the actor against each of these lines and points, getting the minimum time of impact if any
- If a collision will occur, I return a new velocity for the actor along with the time of impact
- The new velocity is meant to make the actor slide along the obstacle
- The time of impact is (supposed to be) a value between zero and one
- The time of impact is a time within the current frame
- The frame is a time period of one
- I regulate the frame rate
- If a collision occurs within the frame time I move the actor by the collision time and subtract that time from the frame time
- I keep testing and moving the actor until no more time is left in the frame
- This is how sliding is able to work
- In the attached code, I've removed any coordinate rounding I used previously, in case they were messing with my results
- You will see several graphical artifacts when the player actor has floating-point coordinates
- Negative time values for collisions can occur
- These always come from the corner collision tests
- I'm convinced the circle-corner collision test is still allowing penetrations
- I'm convinced I ought to fix this to make simulating a level full of actors easier
- Also, the negative time values cause the main actor movement code to go into an infinite loop, since it's largely assuming things go forward in time
- Previously, when I was rounding things, I got around this by checking for a zero (rounded) response vector
- Not possible without rounding
- I kind of want to know what the real problem is
- Be ready to kill the program when testing it
- Previously, when I was rounding things, I got around this by checking for a zero (rounded) response vector
- To find the bug, you sort of have to move against a corner and, while sliding around it, move into the wall edge beyond it
- main.lua
- Line 245, function moveActor - Where collision detection and actor movement occurs
- collision.lua
- All of it, really
- Line 272, function checkCorner - Test actor against corner
- Line 341, function actorVSTile - Test actor against line segments and corners of a tile
- Line 384, function actorVSLevel - Main function that gets tiles actor will likely hit and test actor against those
- Line 179, function checkWall - Get line segments and corners actor will likely hit for a single tile
- levels.lua
- Has some stuff about getting tiles
- Line 69, function tilesInRect
- http://twobitcoder.blogspot.com/2010/04 ... ction.html - Circle-circle collision detection
- http://local.wasp.uwa.edu.au/~pbourke/g ... ineline2d/ - Line intersection
- http://www.physicsforums.com/showthread.php?t=202263 - Vector projection
In conclusion, help on this will be appreciated. I'll also accept hugs.