Hey friends! I’m very confused! I’ve been laying the foundations for a game, and part of that foundation is collision. I know, we all struggle when it comes to collision! It’s for some reason like the hardest thing ever.
I’ve got a solid AABB Swept algorithm down, meaning I’m fairly sure I’m happy where that’s it, however at this point in my confusion I wouldn’t be totally surprised if the problem is there, only a little surprised. I’d expect it to be more likely in the other part of the process, which is when we’re dealing with a tilemap.
The main part of the process when dealing with a tilemap is sorting the tiles by distance from the player. At first I thought this was suspect for snagging, because usually the culprit is not sorting the tiles properly. However, I’ve inspected this process meticulously and am driving myself crazy. There could very well be something wrong, but I can’t figure out what it is.
The issue is apparent whenever you have tiles arranged next to each other, forming a continuous flat surface. The player should be able to glide along this surface smoothly, and at high frame rates it might appear that they are. However, when the speed drops or specifically when the player attempts to jump up against a wall, they very clearly snag. It’s especially clear jumping, because it cancels all vertical velocity and the player falls like a rock. This happens at any speed horizontally too, it’s just much more apparent at slower speeds.
Usually this happens because the tiles are checked in a bad order. Checking a far away tile before checking a closer tile can lead to making an unnecessary adjustment to either component of the player’s velocity. That of course leads to the snagging effect. However, I was under the impression that I did sort the tiles properly. Here’s what code I used:
’Sorting all nearby possible tiles
DEF PROX_TILES(RX,RY,BX,BY,EX,EY)’RX/RY are player coordinates (tiles), BX/BY/EX/EY are the box of tiles to check
DIM PXM[0]
DIM DIST[0]
VAR I,J
FOR I=BX TO EX STEP SGN(EX-BX)
FOR J=BY TO EY STEP SGN(EY-BY)
PUSH PXM,I+J*MAP_WIDTH%’Turns coordinates into single number
PUSH DIST,POW(I-RX,2)+POW(J-RY,2)’Distance FROM PLAYER (no sqrt)
NEXT
NEXT
SORT DIST,PXM
RETURN PXM
END
‘Checking collisions with sorted table
PXM=PROX_TILES(RX,RY,BX,BY,EX,EY)’Sort tiles
VAR I
VAR X,Y
DIM R2[0]
FOR I=0 TO LEN(PXM)-1
Y=FLOOR(PXM[I]/MAP_WIDTH%)’Y tile coordinate
X=PXM[I]-Y*MAP_WIDTH%’X tile coordinate
IF X<0 || Y<0 || X>MAP_WIDTH%-1 || Y>MAP_HEIGHT%-1 THEN CONTINUE
IF RTB[X,Y,0]==-1 THEN CONTINUE’If there is no tile there
R2=PULL_RECT(RTB,X,Y)’Pull single tiles from array
IF LEN(R2)==0 THEN CONTINUE
R1=STD_RECT_VS_RECT(R1,R2)’Resolve collision
NEXT
I’m really not sure what it could be, if the problem isn’t with that code. It seems to still want to adjust for the other tiles anyway, like maybe it does check in the right order but it still makes unnecessary adjustments for the other tiles. I’m not sure why it would do that, because I think in my code I adjust the R1 velocity before it’s used again for the check, but something is clearly not quite right. An interesting quirk that’s probably related is that it still snags when for example the player jumps straight up with no horizontal velocity. I’m not 100% sure why that could be, but it might drag us back to the collision algorithm itself? Any thoughts or input would be greatly appreciated! I hope I’m not going crazy!