Javascript 计算撞击倾斜墙后的角度变化

Javascript 计算撞击倾斜墙后的角度变化,javascript,math,Javascript,Math,我正在用javascript制作一个游戏,其中一个对象应该从墙上反弹。我真的试图让它自己工作,但它从来没有正确的工作 假设有一个球在这个笼子里反弹,蓝色=30°,棕色=60° 球的坐标是已知的。运动的角度是已知的。碰撞点P坐标已知。墙的角度是已知的。球的位置正在使用以下函数更新setInterval函数内的坐标: function findNewPoint(x, y, angle, distance) { var result = {}; result.x =(Math.cos(angle *

我正在用javascript制作一个游戏,其中一个对象应该从墙上反弹。我真的试图让它自己工作,但它从来没有正确的工作

假设有一个球在这个笼子里反弹,蓝色=30°,棕色=60°

球的坐标是已知的。运动的角度是已知的。碰撞点P坐标已知。墙的角度是已知的。球的位置正在使用以下函数更新setInterval函数内的坐标:

function findNewPoint(x, y, angle, distance) {
var result = {};

result.x =(Math.cos(angle * Math.PI / 180) * distance + x);
result.y = (Math.sin(angle * Math.PI / 180) * distance + y);

return result;
因此,在碰撞时,应该有一个函数可以适当地改变球的角度。这似乎是一个非常复杂的问题,因为即使我知道墙是30°,也要知道球从哪一侧撞到墙上。我试着在平面公式中使用一条直线上的反射,还有一些向量,但对我来说从来都不起作用。我并不期待有一个完整的答案和代码,如果有人能建议以什么方式编程,这也会有所帮助

编辑: 谢谢你们的提示,伙计们,我意识到是什么引起了最大的困惑;如果我用鼠标在画布上选择一个角度,则起始坐标0,0位于左下角。但由于画布的起始坐标位于左上角,因此必须考虑这一点

基本上使用此公式计算角度:

function angle(cx, cy, ex, ey) {
var dy = ey - cy;
var dx = ex - cx;
var theta = Math.atan2(dy, dx);
theta *= 180 / Math.PI; 
return theta;
}

如果球从50,50移动到100100,角度将为-45

现在,当撞击墙壁时,此角度将按以下方式更改:


如果我是诚实的,我是通过反复试验得出这些结果的,我不太明白为什么是60和120。如果你假设球的行为就像光从镜子上反弹,那么入射角等于反射角

所以你的棋盘是从0°垂直向上30°。这意味着在球撞击点垂直于板的法线为300°。假设球从280°到达,它必须以320°离开,因为入射角和法线之间的差值,以及反射角和法线之间的差值必须相等


如果假设球的行为类似于光从镜子上反弹,则入射角等于反射角

所以你的棋盘是从0°垂直向上30°。这意味着在球撞击点垂直于板的法线为300°。假设球从280°到达,它必须以320°离开,因为入射角和法线之间的差值,以及反射角和法线之间的差值必须相等


使用角度来移动球并反复计算Cos/Sin是不明智的。而是将单位速度方向向量与组件vx、vy一起使用,如下所示:

new_x = old_x + vx * Velocity_Magnitude * Time_Interval
注意,vx=Cosangle,vy=Sinangle,但对于方向法,很少需要使用三角函数

具有角度Fi的倾斜墙具有法线

nx = -Sin(Fi)
ny = Cos(Fi)
要找到反射,需要计算速度和法线的点积

dot = vx * nx + vy * ny
反射变换后的速度:

vnewx = v.x - 2 * dot * n.x 
vnewy = v.y - 2 * dot * n.y 
使用这些值进行进一步移动

请注意,可以同时使用内部法线方向和外部法线方向,因为“方向翻转”会更改两个组件,并且2*dot*n.x的符号保持不变

示例:

horizontal moving right
vx=1, vy=0   
30 degrees wall has normal 
nx=-1/2, ny=Sqrt(3)/2  
dot = -1/2
vnewx = 1 - 2 * (-1/2) * (-1/2) = 1/2
vnewy = 0 - 2 * (-1/2) * Sqrt(3)/2 = Sqrt(3)/2
(velocity direction angle becomes 60 degrees)

horizontal moving left
vx=-1, vy=0   
330 degrees wall (left bottom corner) has normal 
nx=1/2, ny=Sqrt(3)/2  
dot = -1/2
vnewx = -1 - 2 * (-1/2) * (1/2) = -1/2
vnewy = 0 - 2 * (-1/2) * (Sqrt(3)/2) = Sqrt(3)/2
(velocity direction angle becomes 120 degrees)

使用角度来移动球并反复计算Cos/Sin是不明智的。而是将单位速度方向向量与组件vx、vy一起使用,如下所示:

new_x = old_x + vx * Velocity_Magnitude * Time_Interval
注意,vx=Cosangle,vy=Sinangle,但对于方向法,很少需要使用三角函数

具有角度Fi的倾斜墙具有法线

nx = -Sin(Fi)
ny = Cos(Fi)
要找到反射,需要计算速度和法线的点积

dot = vx * nx + vy * ny
反射变换后的速度:

vnewx = v.x - 2 * dot * n.x 
vnewy = v.y - 2 * dot * n.y 
使用这些值进行进一步移动

请注意,可以同时使用内部法线方向和外部法线方向,因为“方向翻转”会更改两个组件,并且2*dot*n.x的符号保持不变

示例:

horizontal moving right
vx=1, vy=0   
30 degrees wall has normal 
nx=-1/2, ny=Sqrt(3)/2  
dot = -1/2
vnewx = 1 - 2 * (-1/2) * (-1/2) = 1/2
vnewy = 0 - 2 * (-1/2) * Sqrt(3)/2 = Sqrt(3)/2
(velocity direction angle becomes 60 degrees)

horizontal moving left
vx=-1, vy=0   
330 degrees wall (left bottom corner) has normal 
nx=1/2, ny=Sqrt(3)/2  
dot = -1/2
vnewx = -1 - 2 * (-1/2) * (1/2) = -1/2
vnewy = 0 - 2 * (-1/2) * (Sqrt(3)/2) = Sqrt(3)/2
(velocity direction angle becomes 120 degrees)

这是一个函数,它返回给定入射角和表面角度(以度为单位)的反射角。它还确保返回角度在0到359度之间

function angleReflect(incidenceAngle, surfaceAngle){
  var a = surfaceAngle * 2 - incidenceAngle;
  return a >= 360 ? a - 360 : a < 0 ? a + 360 : a;
}
,其中蓝线是入射角,紫线是反射角,黑线是表面


这是一个函数,它返回给定入射角和表面角度(以度为单位)的反射角。它还确保返回角度在0到359度之间

function angleReflect(incidenceAngle, surfaceAngle){
  var a = surfaceAngle * 2 - incidenceAngle;
  return a >= 360 ? a - 360 : a < 0 ? a + 360 : a;
}
,其中蓝线是入射角,紫线是反射角,黑线是表面


我知道你没有要求这样做,但是你考虑过使用javascript物理引擎吗?有很多人做这种事情。如果你感兴趣的话,有一个叫做Phaser的游戏引擎[它非常简单,内置了物理引擎。如果你不想要这个,可以忽略它:谢谢,但这确实是唯一的物理引擎
在我的游戏中,我希望自己能够解决这个问题,现在我已经用node.js做了太多了:。你能描述一下什么不正常吗?另外,试着简化你的问题,从竖直的墙或水平的墙开始。反射角始终是入射角。或者像Cyberchase所说的,角度输入=角度输出。这适用于90度和0度的墙。但是从另一个角度看呢?想想看,如果你把你的整个图像旋转,使30度的墙变成90度的垂直墙,会发生什么。球的角度会如何变化?我认为一件可能会让人困惑的事情是,你说蓝色是30度,棕色是60度,等等。如果你看所有的蓝色墙壁,球的角度会反射的法线是不同的。有些被称为30度,有些被称为-30度,这取决于你从哪里测量。弄清楚你是如何记录球的角度的,并在墙上小心地使用这个标准。有可能把它变成一个功能吗?现在,如果你看我编辑的文章,我只是在不同的角落使用if语句来表示不同的函数。我知道你没有要求这样做,但是你考虑过使用javascript物理引擎吗?有很多人做这种事情。如果你感兴趣的话,有一个叫做Phaser的游戏引擎[这很简单,而且内置了物理引擎。如果你不想这样做,请忽略它:谢谢,但这确实是我游戏中唯一的物理部分,我希望自己能够解决它,现在我已经用node.js做了太多了:。你能描述一下什么工作不正常吗?另外,尝试简化你的问题并有垂直墙或水平墙的艺术。反射角始终是入射角。或者像Cyberchase所说的,角度输入=角度输出。这对90度和0度的墙是正确的。但是其他角度呢?我们想想如果你把整个图像旋转,使30度的墙旋转,会发生什么球的角度会如何变化?我想有一件事可能会让人困惑,那就是你说蓝色是30度,棕色是60度,等等。如果你看所有的蓝色墙壁,球的角度会反射的法线是不同的。有些称为30度,有些称为-30度,这取决于你测量的位置e from。弄清楚你是如何记录球的角度的,并在墙上小心地使用该标准。甚至有可能将其转换为一个函数吗?目前,如果你看我编辑的帖子,我只是在打不同的角时对不同的函数使用if语句。谢谢,这是我需要的。尽管,对于左下角我必须考虑它是一个30度的墙不是330,同样是右上角,而右下+左上角是330。我猜这是因为帆布坐标系从左上角开始。好的。我删除了关于内部法线的句子——没有区别,这就是我需要的。虽然,L。EFT底角我必须考虑它是一个30度的墙不是330,同样是右上角,而右下+左上角是330。我猜这是因为帆布坐标系从左上角开始。好的。我删除了关于内部法线的句子——没有区别。