I need to detect collision circle with any line. I have array with verticles of polygon (x, y) and draw this polygon in loop. For detection I use algorithm, which calculate triangle height. Then I check if this height < 0, then circle collided with line.
The picture, that describe this method:
But I have unexpected result. My circle collide with transparent line (what?). I can't explain how it happens.
Demo at jsfiddle: https://jsfiddle.net/f458rdz6/1/
Function, which check the collisions and response it:
var p = polygonPoints; for (var i = 0, n = p.length; i < n; i++) { var start = i; var end = (i + 1) % n; var x0 = p[start].x; var y0 = p[start].y; var x1 = p[end].x; var y1 = p[end].y; // detection collision var dx = x1 - x0; var dy = y1 - y0; var len = Math.sqrt(dx * dx + dy * dy); var dist = (dx * (this.y - y0) - dy * (this.x - x0)) / len; if (dist < this.radius) { continue; } // calculate reflection, because collided var wallAngle = Math.atan2(dy, dx); var wallNormalX = Math.sin(wallAngle); var wallNormalY = -Math.cos(wallAngle); var d = 2 * (this.velocityX * wallNormalX + this.velocityY * wallNormalY); this.x -= d * wallNormalX; this.y -= d * wallNormalY; } var canvas = document.getElementById("myCanvas"); var ctx = canvas.getContext("2d"); var polygonPoints = [ { x: 240, y: 130 }, { x: 140, y: 100 }, { x: 180, y: 250 }, { x: 320, y: 280 }, { x: 400, y: 50 } ]; var game = { ball: new Ball() }; function Ball() { this.x = canvas.width / 2; this.y = canvas.height - 100; this.oldX = this.x - 1; this.oldY = this.y + 1; this.velocityX = 0; this.velocityY = 0; this.radius = 8; }; Ball.prototype.draw = function() { ctx.beginPath(); ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2); ctx.fillStyle = '#0095DD'; ctx.fill(); ctx.closePath(); }; Ball.prototype.update = function() { var x = this.x; var y = this.y; this.velocityX = this.x - this.oldX; this.velocityY = this.y - this.oldY; this.x += this.velocityX; this.y += this.velocityY; this.oldX = x; this.oldY = y; }; Ball.prototype.collision = function() { var p = polygonPoints; for (var i = 0, n = p.length; i < n; i++) { var start = i; var end = (i + 1) % n; var x0 = p[start].x; var y0 = p[start].y; var x1 = p[end].x; var y1 = p[end].y; // detection collision var dx = x1 - x0; var dy = y1 - y0; var len = Math.sqrt(dx * dx + dy * dy); var dist = (dx * (this.y - y0) - dy * (this.x - x0)) / len; if (dist < this.radius) { continue; } // calculate reflection, because collided var wallAngle = Math.atan2(dy, dx); var wallNormalX = Math.sin(wallAngle); var wallNormalY = -Math.cos(wallAngle); var d = 2 * (this.velocityX * wallNormalX + this.velocityY * wallNormalY); this.x -= d * wallNormalX; this.y -= d * wallNormalY; } }; function drawBall() { ctx.beginPath(); ctx.arc(x, y, ballRadius, 0, Math.PI*2); ctx.fillStyle = "#0095DD"; ctx.fill(); ctx.closePath(); } function drawPolygon() { ctx.beginPath(); ctx.strokeStyle = '#333'; ctx.moveTo(polygonPoints[0].x, polygonPoints[0].y); for (var i = 1, n = polygonPoints.length; i < n; i++) { ctx.lineTo(polygonPoints[i].x, polygonPoints[i].y); } ctx.lineTo(polygonPoints[0].x, polygonPoints[0].y); ctx.stroke(); ctx.closePath(); } function render() { ctx.clearRect(0, 0, canvas.width, canvas.height); drawPolygon(); game.ball.draw(); game.ball.update(); game.ball.collision(); window.requestAnimationFrame(render); } render(); canvas { border: 1px solid #333; } <canvas id="myCanvas" width="480" height="320"></canvas> What the problem? Maybe I need use other method for detect collision? I tried to use this one, but if my circle has high speed this method not working.
Thank you.
