It's much easier to match what's happening with what the code says when you can see it running for yourself. It's also easier to understand what the variables are and how the checks are run. And you'd be surprised by how often someone asks for help and shows a snippet of code, and the problem turns out to be elsewhere. That wasn't the case in this instance, but it's so frequent that I don't bother to even read the code in the first place without a runnable example.
In addition, having runnable code facilitates debugging, printing values and testing possible solutions.
In this case, the problem is that you have the boundary checks wrong. The corners are penetrable, and when a shape penetrates the other through a corner, it jumps as soon as it ceases to be in the corner.
You can fix it by going through each edge and checking if the old position is outside and the new is inside the other shape. Here's an example:
Code: Select all
function collide(object)
for i,v in ipairs(workspace) do
if CheckCollision(object.xpos,object.ypos,object.x,object.y,v.xpos,v.ypos,v.x,v.y) and v ~= object then
if object.olypos >= v.ypos + v.y and object.ypos < v.ypos + v.y then
object.vely = 0
object.ypos = v.ypos + v.y
end
if object.olypos <= v.ypos - object.y and object.ypos > v.ypos - object.y then
object.vely = 0
object.ypos = v.ypos - object.y
end
if object.olxpos >= v.xpos + v.x and object.xpos < v.xpos + v.x then
object.velx = 0
object.xpos = v.xpos + v.x
end
if object.olxpos <= v.xpos - object.x and object.xpos > v.xpos - object.x then
object.velx = 0
object.xpos = v.xpos - object.x
end
end
end
end
If you understand how the CheckCollision function works, you shouldn't have much problem understanding that code. I'll explain the first if; the rest are just the same but applied to the other boundaries.
The check
object.olypos >= v.ypos + v.y means that the top border of the object in its previous position is below the bottom border of each object being checked. That is, the old position was not penetrating the object. Similarly, if the expression
object.ypos < v.ypos + v.y is true, it means that the new position is penetrating the object. When both conditions are true, it means that this edge has intervened in the collision (which we know is happening because CheckCollision told us) and the position for this edge needs to be fixed.
Mind you, this check is not perfect. If the speed is big you can have the "bullet through wall" effect, because you're not applying swept collisions. Swept collisions are much harder to implement. But with reasonable speeds and object sizes there shouldn't be much trouble. If you have trouble with that you can always make several updates per frame. There's another potential issue, which is that one object may start inside the other. That can happen in some corner cases if you have boxes close to each other.
To prevent all those weird cases, you can use a collision library instead of trying to implement collisions yourself.