Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/406.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 使用基于速度的二维运动修复简单碰撞检测_Javascript_Three.js_Collision Detection - Fatal编程技术网

Javascript 使用基于速度的二维运动修复简单碰撞检测

Javascript 使用基于速度的二维运动修复简单碰撞检测,javascript,three.js,collision-detection,Javascript,Three.js,Collision Detection,在这种情况下,你可以用箭头移动“玩家”方格,放置一盏有空间的灯,并被推到相反的方向,以防止从任何方向越过蓝线。“玩家”使用x和y速度变量创建运动,如果检测到碰撞,则将它们乘以-1(+某个值) 问题是,在被推离墙壁后,“玩家”会被卡在一个位置,在这个位置上,只有从墙壁向后移动才有可能,同时看起来被卡在与墙壁垂直的轴上。(例如,如果墙壁位于玩家的顶部,则您只能移动到底部,而不能在撞击墙壁后向左或向右移动) 理论上,我想要一个平滑的滑动碰撞检测,在这里,卡在墙上的玩家会慢慢地从左侧或右侧滑下 取决于是

在这种情况下,你可以用箭头移动“玩家”方格,放置一盏有空间的灯,并被推到相反的方向,以防止从任何方向越过蓝线。“玩家”使用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);
};
设xVelocity=0;
设yVelocity=0;
var blockedMapGrid=[[0,30]、[0,50]、[0100]、[0150]、[0200]、[0250],
[50,0],[100,0],[150,0],[200,0],[250,0],[300,0]];
var animate=函数(){
if(键状态[37]){
xVelocity-=1;
}
if(键状态[38]){
yVelocity+=1;
}
if(键状态[39]){
x速度+=1;
}
if(键状态[40]){
yVelocity-=1;
}
对于(变量i=0;i
探测器的这部分错误:

Math.abs(player.position.x - blockedMapGrid[i][0]) + 
   Math.abs(player.position.y - blockedMapGrid[i][1]) < 36
您可以改变检测到碰撞时的操作,但这里的关键是使用4个条件查找两个框是否重叠

更新

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

根据经验,在碰撞后,如果不确保角色回到“清除”位置,即玩家的边界框不与任何障碍物重叠,则不得使用
velocity=-velocity
。否则您将陷入无限循环
冲突?->vel=-vel,pos+=vel*t->collision->…
速度从负向正反弹回来,而不允许玩家离开墙

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

另一种方法是记住最后一个已知的“好”位置,只有当角色返回到前一个位置时,才返回对角色的控制,可能是在动画或一系列无法控制的动作之后


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

谢谢你的评论-我考虑过使用带半径的点,因为它在数组中占用的空间更少。但我认为定制形状的矩形可以弥补这一差异
尽管我遇到了“矩形内滑动”的错误,但您的方法仍然有效。当你跑到墙边,同时按下相反方向的箭头时,玩家进入盒子,开始在阻塞区域以几乎0的速度移动。这是一件平常的事吗?我可以将反弹速度设置为略高于传入速度,但不确定这是最好的way@SanchezPanza我将更新一个答案,以帮助反弹。
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;
  }
}