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

时间:2017-07-17 21:47:25

标签: javascript math

我正在用javascript制作游戏,其中一个物体应该从墙壁反弹。我真的试图让它自己工作,但它永远不会正常工作。

让我们说这个笼子里面有一个球弹跳(蓝色= 30°,棕色= 60°);

bouncing ball in cage

球的坐标是已知的。运动角度是已知的。碰撞点(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)移动到(100,100),角度将为-45。

现在,当撞击墙壁时,此角度会以下列方式变化: angle bounces

如果我诚实,我从试验和错误中得到了这些,我真的不明白为什么正好是60和120.

3 个答案:

答案 0 :(得分:2)

使用角度移动球并一次又一次地计算Cos / Sin是不明智的。而是使用单位速度方向向量和组件vx, vy,如下所示:

new_x = old_x + vx * Velocity_Magnitude * Time_Interval

请注意vx = Cos(angle), vy = Sin(angle),但使用方向法,您很少需要使用三角函数。

角度为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)

答案 1 :(得分:1)

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

因此,您的电路板与0°(直线向上)成30°角。法线(球击中球的垂直方向)是300°。假设球从280°到达,它必须以320°离开,因为入射角与法线之间的差异以及反射角和法线必须相等。

答案 2 :(得分:1)

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

function angleReflect(incidenceAngle, surfaceAngle){
  var a = surfaceAngle * 2 - incidenceAngle;
  return a >= 360 ? a - 360 : a < 0 ? a + 360 : a;
}

Here's a demonstration,其中蓝线是入射角,紫线是反射角,黑线是表面。

demonstration of angle of reflection