Skip to content

Instantly share code, notes, and snippets.

@snorpey
Last active March 1, 2024 13:43
Show Gist options
  • Star 11 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save snorpey/8134c248296649433de2 to your computer and use it in GitHub Desktop.
Save snorpey/8134c248296649433de2 to your computer and use it in GitHub Desktop.
Calculate collision between circle and rotated rectangle
// Ported to JavaScript from
// http://www.migapro.com/circle-and-rotated-rectangle-collision-detection/
//
// An example:
// var circle: { x: 20, y: 10, radius: 20 };
// var rect: { x: 30, y: 30, width: 100, height: 100, rotation: Math.PI / 2 };
// collideCircleWithRotatedRectangle( circle, rect );
// // returns true.
//
//
// Please note:
// This code assumes that rect.x and rect.y are the CENTER coordinates
// of the rectangle. You may want to to change this.
// Also rotation values need to be in RADIANS.
function collideCircleWithRotatedRectangle ( circle, rect ) {
var rectCenterX = rect.x;
var rectCenterY = rect.y;
var rectX = rectCenterX - rect.width / 2;
var rectY = rectCenterY - rect.height / 2;
var rectReferenceX = rectX;
var rectReferenceY = rectY;
// Rotate circle's center point back
var unrotatedCircleX = Math.cos( rect.rotation ) * ( circle.x - rectCenterX ) - Math.sin( rect.rotation ) * ( circle.y - rectCenterY ) + rectCenterX;
var unrotatedCircleY = Math.sin( rect.rotation ) * ( circle.x - rectCenterX ) + Math.cos( rect.rotation ) * ( circle.y - rectCenterY ) + rectCenterY;
// Closest point in the rectangle to the center of circle rotated backwards(unrotated)
var closestX, closestY;
// Find the unrotated closest x point from center of unrotated circle
if ( unrotatedCircleX < rectReferenceX ) {
closestX = rectReferenceX;
} else if ( unrotatedCircleX > rectReferenceX + rect.width ) {
closestX = rectReferenceX + rect.width;
} else {
closestX = unrotatedCircleX;
}
// Find the unrotated closest y point from center of unrotated circle
if ( unrotatedCircleY < rectReferenceY ) {
closestY = rectReferenceY;
} else if ( unrotatedCircleY > rectReferenceY + rect.height ) {
closestY = rectReferenceY + rect.height;
} else {
closestY = unrotatedCircleY;
}
// Determine collision
var collision = false;
var distance = getDistance( unrotatedCircleX, unrotatedCircleY, closestX, closestY );
if ( distance < circle.radius ) {
collision = true;
}
else {
collision = false;
}
return collision;
}
function getDistance( fromX, fromY, toX, toY ) {
var dX = Math.abs( fromX - toX );
var dY = Math.abs( fromY - toY );
return Math.sqrt( ( dX * dX ) + ( dY * dY ) );
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment