How to perform a sliding collision between a square and a circle?

Please point me to the duplicate if this has been asked before. I couldn't find it.

Basically, I am creating a 2d top-down game where the player is represented by a circle, and the tiles are represented by 16x16 squares. I have gotten collision detection working, such that the player cannot collide with tiles, by using the following algorithm:

let curPosition = player.position;
let newPosition = player.position + player.velocity;

if (canTouchPosition(newPosition.x, curPosition.y)) {
player.position.x = newPos.x;
}

if (canTouchPosition(curPosition.x, newPosition.y)) {
player.position.y = newPos.y;
}

if (canTouchPosition(newPosition.x, newPosition.y)) {
player.position.x = newPos.x;
player.position.y = newPos.y;
}


This works, except there's a problem. If the player is on the edge of a tile and moving to the right, I want them to slide past it, instead of getting stuck. Like so:

See how currently the circle is stuck on the corner when trying to move right? Instead I want it to slide along the corner until it is able to move freely, and then continue moving to the right. I can't quite figure this out. I figure a circle would make this easier, but if a square is instead easier to perform this operation on, maybe I'll use one of those instead? I mostly just want to get it working.

• Thanks for the links. This seems really complicated though? I can't imagine something like this is more than a few lines of code, no? Mar 28, 2021 at 22:49
• It depends how general it needs to be. The two answers above aren't for your exact use case, but for more general situations that could include circles of different sizes or other obstacle shapes. Take the inspiration, then simplify to the parts you need. Mar 28, 2021 at 23:14
• Yeah the issue is that I'm having trouble understanding all the math in the answers I've seen, so I was looking for a more specific solution, so that I wouldn't be so overwhelmed. Mar 28, 2021 at 23:16
• Displacing along the minimum separation vector might be enough for your needs then. You can get small glitches that way, but it is much simpler than a water-tight continuous collision solution. Mar 28, 2021 at 23:18

An easy way would be to think of the circle as a rectangle still, so just have a circle displayed, but still be rectangle colliding. And then instead of preventing movement, move first, holding the updated x,y somewhere that is not the final x,y, and then apply that movement if there is not collision, if there is adjust, which you're doing. But let the collision method return the point of collision, for example:

        this._pos.x += this._veloc.x*this._deltaTime;
this._pos.y += this._veloc.y*this._deltaTime;

var pgy, pgx;
pgx = this.isLeftPushingOnMap(this._lastPos,this._pos,this._veloc,this._map,this._tw,this._th);
if(pgx > 0) {
this._pLeft = 1;//pushing left
this._pos.x = pgx +1;
this._veloc.x = 0;
} else {

this._pLeft = 0;
}

...
this.setX( this._pos.x );
this.setY( this._pos.y );