gpt4 book ai didi

javascript - 是否有一种算法可以检测我与多边形的哪一侧发生碰撞?

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:28:38 29 4
gpt4 key购买 nike

如果给定一个 n 边的多边形,以及一条长度为 k 的线(在 x,y 和 Angular a),是否有一种算法可以检测我与多边形的哪一侧(如果有)发生碰撞?到目前为止,我已经求助于测试 x,y 是否在多边形之外,然后遍历多边形的每条边,计算到每一端的距离。这是一个JS Fiddle展示了我创造的世界。

这是 JavaScript(HTML 和 CSS 真的不值得复制):

var eventLoop,
maxVelocity = 10,
agility = 5,
baseLength = 5,
degree = ((2*Math.PI)/360),
world = document.getElementById('world'),
context = world.getContext("2d"),
boundry = [[180, 120],[240, 60],[360, 40],[420, 120],[360, 220],[350, 240],[360, 265],[470,360],[450,480],[360,540],[240,550],[140,480],[120,470],[100,360],[120,300],[220,240],[240,220]],
camera = {
location: {
x:300,
y:90
},
angle: 0,
velocity: 0
},
engine = {
drawWorld: function(shape, context) {
var point,
index,
size = shape.length;

context.clearRect(0, 0, world.width, world.height);
context.beginPath();
for(index = 0; index < size; index++) {
point = shape[index];
if(index == 0) {
context.moveTo(point[0], point[1]);
} else {
context.lineTo(point[0], point[1]);
}
}
context.closePath();
context.stroke();
},
drawCamera: function(camera, context) {
var a = camera.location,
b = this.calcNextPoint(camera, 1);

context.beginPath();
context.moveTo(a.x, a.y);
context.lineTo(b.x, b.y);
context.stroke();

context.beginPath();
context.arc(a.x, a.y, baseLength, 0, Math.PI*2, true);
context.closePath();
context.stroke();
},
calcNextPoint: function(camera, moment) {
return {
x: camera.location.x + ((camera.velocity*(1/moment))*Math.sin(camera.angle)),
y: camera.location.y + ((camera.velocity*(1/moment))*(Math.cos(camera.angle)))
};
},
isInside: function(point, shape) {
var i, j, c = 0;
for (i = 0, j = shape.length - 1; i < shape.length; j = i++) {
if (((shape[i][1] > point.y) != (shape[j][1] > point.y)) && (point.x < (shape[j][0] - shape[i][0]) * (point.y - shape[i][1]) / (shape[j][1] - shape[i][1]) + shape[i][0])) {
c = !c;
}
}
return c;
}
};

document.onkeydown = function(e) {
e = e || window.event;
if (e.keyCode == '37') {
// left arrow
camera.angle += degree*agility;
}
else if (e.keyCode == '39') {
// right arrow
camera.angle -= degree*agility;
}
else if (e.keyCode == '38') {
// up arrow
camera.velocity += 1;
if(camera.velocity > maxVelocity) {
camera.velocity = maxVelocity;
}
}
else if (e.keyCode == '40') {
// down arrow
camera.velocity -= 1;
if(camera.velocity < 0) {
camera.velocity = 0;
}
}
}

engine.drawWorld(boundry, context);
engine.drawCamera(camera, context);

eventLoop = setInterval(function() {
engine.drawWorld(boundry, context);
engine.drawCamera(camera, context);
if(engine.isInside(camera.location, boundry)) {
camera.location = engine.calcNextPoint(camera, 1);
}
}, 100);

我一直在玩弄一些模拟游戏的 2-Demental 版本的 JavaScript Flower通过 ThatGameComapny,最终我想尝试实现 Oculus Rift 版本。我要解决的下一个问题是在玩家与边缘发生碰撞后将玩家变回多边形的例程。

最佳答案

所以您基本上想知道给定线与多边形的哪些边相交,对吧?

这只是几个 linear equations的简单处理 表示边缘(不等式,更准确地说)。您已经很好地实现了 inside 操作,它也能做到这一点。所有这些算法的共同点是比较在线的哪一侧 [x1, y1] - [x2, y2][x, y ] 谎言:

compare = function (a, b) { // classical compare function, returns -1, 0, 1
return a < b ? -1 : (a == b ? 0 : 1);
}
...
_lineSide: function (x, y, x1, y1, x2, y2) {
return compare(x - x1, (x2 - x1) * (y - y1) / (y2 - y1));
}

如果 [x, y] 位于 [x1, y1] - [x2, y2] 线的一侧,此函数将返回 -1 , 1 表示另一边,0 表示恰好位于直线上。这里哪一侧是哪一侧并不重要,只是将它们分开。但是,当 y2 - y1 为零或接近零时,这将不起作用。在这种情况下,您必须 x-y 翻转情况:

lineSide: function (x, y, x1, y1, x2, y2) {
var eps = 1e-20; // some very small number
if (Math.abs(y2 - y1) > eps) // this way we avoid division by small number
return _lineSide(x, y, x1, y1, x2, y2);
else if (Math.abs(x2 - x1) > eps) // flip the situation for horizontal lines
return _lineSide(y, x, y1, x1, y2, x2);
else // edge has close-to-zero length!
throw new this.zeroLengthLineException()
},
zeroLengthLineException: function () {},

现在测试两行 [x1, y1] - [x2, y2][x3, y3] - [x4, y4] 相交很容易。只要看看 [x1, y1][x2, y2] 是否位于 [x3, y3] 的对面 - [x4, y4],如果 [x3, y3][x4, y4] 位于 [x1, y1 的对面] - [x2, y2]。如果是,则线相交!

// proper: true/false (default false) - if we want proper intersection, i.e. just 
// touching doesn't count
linesIntersect: function (x1, y1, x2, y2, x3, y3, x4, y4, proper) {
var min_diff = proper ? 2 : 1;
return Math.abs(this.lineSide(x1, y1, x3, y3, x4, y4) -
this.lineSide(x2, y2, x3, y3, x4, y4)) >= min_diff
&& Math.abs(this.lineSide(x3, y3, x1, y1, x2, y2) -
this.lineSide(x4, y4, x1, y1, x2, y2)) >= min_diff;
},

最终解决方案 - http://jsfiddle.net/gLTpT/7/

现在,最终解决方案很简单:通过在循环中调用linesIntersect 来检查给定线与所有多边形边的交点:

http://jsfiddle.net/gLTpT/7/

enter image description here

关于javascript - 是否有一种算法可以检测我与多边形的哪一侧发生碰撞?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18238211/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com