简体   繁体   English

撞墙后计算角度变化

[英]Calculate angle change after hitting a tilted wall

I'm making a game in javascript, where an object is supposed to bounce from walls. 我正在用javascript做游戏,该对象应该从墙壁反弹。 I really tried to get it to work myself, but it never works correctly. 我确实试图让它自己工作,但是它永远无法正常工作。

Let's say theres a ball bouncing inside this cage (blue = 30°, brown = 60°); 假设有一个球在笼子里弹跳(蓝色= 30°,棕色= 60°);

关在笼子里的弹跳球

The ball's coordinates are known. 球的坐标是已知的。 The angle of movement is known. 运动角度是已知的。 The point of collision (P) coordinates are known. 碰撞点(P)坐标是已知的。 The angle of the wall is known. 墙壁的角度是已知的。 The ball's position is updating it's coordinates inside a setInterval function using this function: 球的位置正在使用以下函数在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;

So, upon colliding, there should be a function that properly changes the ball's angle. 因此,在发生碰撞时,应该有一个可以正确改变球角度的功能。 It's a very complicated problem it seems, because even if I know that the wall is 30°, its important to know from what side the ball is colliding into it. 看来这是一个非常复杂的问题,因为即使我知道墙是30°,也很重要的一点是要知道球从哪一侧碰撞到其中。 I tried using the "Reflection across a line in the plane" formula and also some vectors, but it never worked out for me. 我尝试使用“在平面上的直线上的反射”公式以及一些矢量,但是它对我没有用。 I'm not expecting a complete answer with code, if someone could suggest in what way this should be programmed, it would help aswell. 我不希望代码有完整的答案,如果有人可以建议应该以哪种方式进行编程,那么它也会有所帮助。

Edit: Thanks for your tips guys, I realized what was causing the most confustion; 编辑:感谢您的提示,我意识到造成最大混乱的原因是什么; if I select an angle on the canvas with my mouse, the starting coordinate(0,0) is in the bottom left corner. 如果使用鼠标在画布上选择一个角度,则起始坐标(0,0)在左下角。 But since the canvas' starting coordinate is in the top left corner, this has to be considered. 但是,由于画布的起始坐标位于左上角,因此必须考虑这一点。

Basically using this formula for calculating the angle: 基本上使用此公式来计算角度:

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;

} }

if the ball moved from (50,50) to (100,100), the angle would be -45. 如果球从(50,50)移至(100,100),则角度将为-45。

Now, this angle changes in the following way when hitting walls: 现在,撞墙时此角度将以以下方式变化: 角度反弹

If im honest, I got these out of trial and error, am not really understanding why exactly 60 and 120. 如果说实话,我是从反复试验中得出这些结论的,不是很了解为什么精确地为60和120。

It is not wise to use angle for moving ball and calculate Cos/Sin again and again. 用角度移动球并一次又一次地计算Cos / Sin是不明智的。 Instead use unit velocity direction vector with components vx, vy like this: 而是使用具有分量vx, vy单位速度方向向量vx, vy如下所示:

new_x = old_x + vx * Velocity_Magnitude * Time_Interval

Note that vx = Cos(angle), vy = Sin(angle) , but with direction approach you seldom need to use trigonometric functions. 请注意, vx = Cos(angle), vy = Sin(angle) ,但是使用方向方法时,您几乎不需要使用三角函数。

Tilted wall with angle Fi has normal 倾斜角度为Fi的倾斜墙具有法线

nx = -Sin(Fi)
ny = Cos(Fi)

To find reflection , you need to calculate dot product of velocity and normal 要找到反射,您需要计算速度与法线的点积

dot = vx * nx + vy * ny

Velocity after reflection transforms: 反射后的速度转换:

vnewx = v.x - 2 * dot * n.x 
vnewy = v.y - 2 * dot * n.y 

Use these values for further moving 使用这些值进一步移动

(note that you can use both internal and external normal direction, because direction flip changes both components, and sign of 2 * dot * nx remains the same) (请注意,您可以同时使用内部和外部法线方向,因为方向翻转会同时改变这两个分量,并且2 * dot * nx符号保持不变)

Examples: 例子:

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)

If you're assuming that the ball behaves like light bouncing off a mirror, then the angle of incidence equals the angle of reflection. 如果您假设球的行为就像是从镜子反射回来的光,那么入射角等于反射角。

So your board is 30° from 0° (straight up). 因此,您的电路板与0°呈30°(直线向上)。 The means the normal (perpendicular to the board at the point the ball hits ) is 300°. 指法线(垂直于板在球击中点处)为300°。 Say the ball arrives from 280°, it must leave at 320° as the difference between the angle of incidence and the normal and the angle of reflection and the normal must be equal. 假设球从280°到达,它必须离开320°,因为入射角与法线之间的差和反射角与法线之间的差必须相等。

Here is a function that returns the angle of reflection given an angle of incidence and a surface angle (in degrees). 这是在给定入射角和表面角度(以度为单位)的情况下返回反射角的函数。 It also ensures that the returned angle is between 0 and 359 degrees. 它还确保返回角度在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 , where the blue line is the angle of incidence, the purple line is the angle of reflection, and the black line is the surface. 这是一个演示 ,其中蓝线是入射角,紫线是反射角,黑线是表面。

反射角的演示

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM