问题描述
需要在任何多边形内部检测和响应球碰撞的良好方法。
例如,我有一个方法,
ctx.beginPath
ctx.arc(x,y,ballRadius,0,Math.PI * 2);
ctx.fillStyle =#0095DD
ctx.fill();
ctx.closePath();
检测和响应碰撞非常简单。
if(x + dx> canvas.width-ballRadius || x + dx< ballRadius){
dx = -dx;
}
if(y + dy> canvas.height-ballRadius || y + dy< ballRadius){
dy =
}
但我有一个多边形:变量的位置(x和y)
var polygonPoints = [
{
x:240,
y:30
},
{
x:140,
y:100
},
{
x:180,
y:250
},
{
x:320,
y:280
},
{
x:400,
y:50
} b $ b
];
多边形:
ctx.beginPath();
ctx.strokeStyle ='#333';
ctx.moveTo(polygonPoints [0] .x,polygonPoints [0] .y);
for(var i = 1,n = polygonPoints.length; i ctx.lineTo(polygonPoints [i] .x,polygonPoints [i] .y);
}
ctx.lineTo(polygonPoints [0] .x,polygonPoints [0] .y);
ctx.stroke();
ctx.closePath()
如何检测和响应多边形内的碰撞?
在
下面是一些显示如何进行计算的伪代码:
var wallNormalAngle = wallAngle-PI / 2; //假定顺时针角度计算
var differenceAngle = incidenceAngle - wallNormalAngle;
var reflectionAngle = incidenceAngle + 2 * differenceAngle
Need to code good method for detection and response ball-to-wall collision inside any polygon.
For example, I have a method which draw a ball which fly inside a rectangle.
ctx.beginPath();
ctx.arc(x, y, ballRadius, 0, Math.PI*2);
ctx.fillStyle = "#0095DD";
ctx.fill();
ctx.closePath();
Detect and response that collision very simple.
if(x + dx > canvas.width-ballRadius || x + dx < ballRadius) {
dx = -dx;
}
if(y + dy > canvas.height-ballRadius || y + dy < ballRadius) {
dy = -dy;
}
But I have a polygon: variable with positions (x and y) of each point.
var polygonPoints = [
{
x: 240,
y: 30
},
{
x: 140,
y: 100
},
{
x: 180,
y: 250
},
{
x: 320,
y: 280
},
{
x: 400,
y: 50
}
];
And function wich draw my polygon:
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();
How I can detect and response collisions inside a polygon?
Demo on jsfiddle.
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var ballRadius = 10;
var x = canvas.width/2;
var y = canvas.height-30;
var dx = 2;
var dy = -2;
var polygonPoints = [
{
x: 240,
y: 30
},
{
x: 140,
y: 100
},
{
x: 180,
y: 250
},
{
x: 320,
y: 280
},
{
x: 400,
y: 50
}
];
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 draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawBall();
drawPolygon();
if(x + dx > canvas.width-ballRadius || x + dx < ballRadius) {
dx = -dx;
}
if(y + dy > canvas.height-ballRadius || y + dy < ballRadius) {
dy = -dy;
}
x += dx;
y += dy;
window.requestAnimationFrame(draw);
}
draw();
canvas {
border: 1px solid #333;
}
<canvas id="myCanvas" width="480" height="320"></canvas>
Here's how to test for circle (ball) collisions) versus any line in your polygon.
First, calculate the closes point on a line relative to your ball:
function calcClosestPtOnSegment(x0,y0,x1,y1,cx,cy){
// calc delta distance: source point to line start
var dx=cx-x0;
var dy=cy-y0;
// calc delta distance: line start to end
var dxx=x1-x0;
var dyy=y1-y0;
// Calc position on line normalized between 0.00 & 1.00
// == dot product divided by delta line distances squared
var t=(dx*dxx+dy*dyy)/(dxx*dxx+dyy*dyy);
// calc nearest pt on line
var x=x0+dxx*t;
var y=y0+dyy*t;
// clamp results to being on the segment
if(t<0){x=x0;y=y0;}
if(t>1){x=x1;y=y1;}
return({ x:x, y:y, isOnSegment:(t>=0 && t<=1) });
}
Second, test if the ball is close enough to collide with that line like this:
var dx=ballX-nearestX;
var dy=ballY-nearestY
var isColliding=(dx*dx+dy*dy<ballRadius*ballRadius);
Finally, if the ball collided with that side, calculate the ball's reflection angle (== its outgoing angle):
Here's an illustration of the angles involved in the calculation:
- The red line indicates the ball's incoming angle.
- The gold line indicates the ball's outgoing angle.
- The outgoing angle equals the incoming angle plus twice the diff-angle.
And here's some pseudo-code showing how to do the calculation:
var wallNormalAngle = wallAngle-PI/2; // assuming clockwise angle calculations
var differenceAngle = incidenceAngle - wallNormalAngle;
var reflectionAngle = incidenceAngle + 2 * differenceAngle
这篇关于检测和响应任何多边形内的球碰撞的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!