Javascript - Collision detection
Circle vs Circle tip: delay event after collision
by katalin_2003
HTML
<h1>Mouse over/tap to test collisions</h1>
CSS
html {
/* height: 100%;*/
}
body {
transition: 1s all;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
align-content: center;
height: 100%;
font-size: 20pt;
font-family: sans-serif;
font-weight: bold;
font-variant: small-caps;
text-shadow: 2px 2px 10px rgba(0, 0, 0, 0.25);
background-size: 100vmax;
}
canvas {
background: white;
border-top: 1px solid #CCC;
border-left: 1px solid #CCC;
border-right: 1px solid #666;
border-bottom: 1px solid #666;
border-radius: 6px;
box-shadow: 2px 2px 20px rgba(0, 0, 0, 0.65);
padding: 10px;
margin: 30px;
outline: 1px solid #CCC;
outline-offset: -10px;
}
JavaScript
var canvas = document.body.appendChild(document.createElement("canvas")),
ctx = canvas.getContext("2d"),
ballA = {
x: 65,
y: 65,
radius: 100
},
ballB = {
x: 65,
y: 65,
radius: 50
};
canvas.width = canvas.height = 512;
canvas.addEventListener("mousemove", function(e) {
ballB.x = e.offsetX;
ballB.y = e.offsetY;
}, false);
function aabb(a, b) {
if (a.x + a.radius + b.radius > b.x && a.x < b.x + a.radius + b.radius && a.y + a.radius + b.radius > b.y && a.y < b.y + a.radius + b.radius) {
return true;
}
return false;
}
function dist(a, b) {
return Math.sqrt(
((a.x - b.x) * (a.x - b.x)) + ((a.y - b.y) * (a.y - b.y)));
}
function collides(a, b) {
if (aabb(a, b)) {
var distance = dist(a, b);
if (distance < a.radius + b.radius) {
return true;
}
}
return false;
}
function collisionPoint(a, b) {
return {
x: ((a.x * b.radius) + (b.x * a.radius)) / (a.radius + b.radius),
y: ((a.y * b.radius) + (b.y * a.radius)) / (a.radius + b.radius)
};
}
function animate() {
var collided = collides(ballA, ballB);
ctx.clearRect(0, 0, canvas.width, canvas.height);
if (collided) {
ctx.fillStyle = "red";
document.body.style.backgroundColor = '#ECC';
} else {
ctx.fillStyle = "green";
document.body.style.backgroundColor = '#CEC';
}
ctx.beginPath();
ctx.arc(ballA.x, ballA.y, ballA.radius, 0, Math.PI * 2);
ctx.fill();
ctx.beginPath();
ctx.arc(ballB.x, ballB.y, ballB.radius, 0, Math.PI * 2);
ctx.fill();
if (aabb(ballA, ballB)) {
ctx.strokeStyle = "red";
} else {
ctx.strokeStyle = "green";
}
ctx.strokeRect(ballA.x - ballA.radius, ballA.y - ballA.radius, ballA.radius * 2, ballA.radius * 2);
ctx.strokeRect(ballB.x - ballB.radius, ballB.y - ballB.radius, ballB.radius * 2, ballB.radius * 2);
if (collided) {
console.log("circles HIT!");
var point = collisionPoint(ballA, ballB);
ctx.fillStyle = "blue";
ctx.beginPath();
...