gpt4 book ai didi

javascript - 修复基于速度的二维运动的简单碰撞检测

转载 作者:行者123 更新时间:2023-11-29 23:05:46 25 4
gpt4 key购买 nike

在此codePen demo你可以用箭头移动“玩家”正方形,放置一个有空间的灯,并且应该被推到相反的方向而停止从任何方向越过蓝线。 “玩家”使用 x 和 y 速度变量来创建运动,如果检测到碰撞,则将它们乘以 -1(+ 某个值)。
问题是,在被推离墙壁后,“玩家”被卡在一个只能从墙壁向后移动的位置,同时看起来卡在垂直轴上。 (例如 - 如果墙在玩家的顶部,你只能移动到底部,而不是在撞到墙后向左或向右移动)
从理论上讲,我想要一个平滑的滑动碰撞检测,卡在墙上的玩家会慢慢地向左或向右滑动 取决于是否按下左箭头或右箭头。 (四处玩耍我能够实现这一点,但总是一个方向会“流动”,使玩家向某个方向滑动)
我考虑过使用射线或其他一些方法来检测命中,但它们似乎需要比只是简单的方法。将不胜感激构建可扩展碰撞检测的任何输入和任何建议,这是我在演示中进行移动和碰撞检测的基本代码:

let xVelocity = 0;
let yVelocity = 0;
var blockedMapGrid = [[0,30],[0,50],[0,100],[0,150],[0,200],[0,250],
[50,0],[100,0],[150,0],[200,0],[250,0],[300,0]];


var animate = function() {



if (keyState[37]) {

xVelocity -= 1;

}
if (keyState[38]) {

yVelocity += 1;
}
if (keyState[39]) {
xVelocity += 1;

}
if (keyState[40]) {
yVelocity -= 1;

}

for (var i = 0; i < blockedMapGrid.length; i++) {
if (Math.abs(player.position.x - blockedMapGrid[i][0]) +
Math.abs(player.position.y - blockedMapGrid[i][1]) < 36) {
xVelocity = -xVelocity * 1.2;
yVelocity = -yVelocity * 1.2;


console.log("Blocked by " + blockedMapGrid[i][0])
};
}


player.position.x = player.position.x + xVelocity;
player.position.y = player.position.y + yVelocity;
yVelocity *= 0.80;
xVelocity *= 0.80;

camera.position.x = player.position.x;
camera.position.y = player.position.y;

requestAnimationFrame(animate);


renderer.render(scene, camera);
};

最佳答案

你的检测器的这部分是错误的:

Math.abs(player.position.x - blockedMapGrid[i][0]) + 
Math.abs(player.position.y - blockedMapGrid[i][1]) < 36

基本上,在这里,您通过使用添加的绝对值而不是平方和的根来估算从玩家到网格上的点的距离。事实上,您不需要如此复杂的网格(重复线)和距离。

您似乎在进行轴对齐边界框 (AABB) 检测。有 plentyresources在互联网上如何优化它。

但一般的做法是这样的。您的网格阵列应由带有 (x,y,w,h) 的框组成措施。可以是细的,长的,方形的,任何东西。我们还假设您的玩家有一个边界框 (player.x, player.y, player.w, player.h) , 然后

for (var i = 0; i < grid.length; i++) {
if (player.x < grid[i].x + grid[i].w &&
player.x + player.w > grid[i].x &&
player.y < grid[i].y + grid[i].h &&
player.y + player.h > grid[i].y) {
//collision detected! move player to previous known position
break;
}
}

您可以改变检测到碰撞时的操作,但使用 4 个条件判断两个框是否重叠是这里的关键。

更新

问题中的代码引起的另一个问题是检测到碰撞后“弹跳”或“卡住”。

根据经验,永远不要使用 velocity = -velocity碰撞后也没有确保 Angular 色回到“清晰”状态,即玩家的边界框没有与任何障碍物重叠。否则你将陷入无限循环 collision? -> vel = -vel, pos += vel*t -> collision -> ...速度从负向正向反弹,并且不允许玩家离开墙。

修复它的最简单方法是首先在临时变量中计算玩家的新位置,检查新位置是否没有碰撞,然后才将其永久化并调用 render() ,否则只需忽略它并在不移动播放器的情况下进行渲染。

另一种方法是记住最后一个已知的“好”位置,并且只在 Angular 色返回到之前的位置时才交还对 Angular 色的控制权,可能是在动画或一系列无法​​控制的 Action 之后。

还有更复杂的方法,主要涉及某种物理模拟,让 Angular 色在多个障碍物之间弹跳,前提是控制输入不能克服惯性——想想一辆汽车在湿滑的道路上行驶,或者一艘船撞到多棵树上。但无论哪种方式,在检测到碰撞之后和调用“render()”之前,您都必须将 Angular 色放置在物理上可能的位置,否则它将著名地“卡在纹理中”。

关于javascript - 修复基于速度的二维运动的简单碰撞检测,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54815264/

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