弹跳物体的三角函数
Trigonometry to bounce an object
我需要在绘图区域内移动对象。该物体随机移动,每当它撞到墙壁时它就会 pi/2 弹跳。 (比如'pong'比赛中的球)
这很容易使用两个增量 'dx' 和 'dy',当它与限制发生冲突时,我只需更改正确的符号。但是在这个上,我的物体在 vcos(theta) = x 和 vsin(theta) = y 之间移动。当它撞到墙上时,我需要 theta 在自身上加上 pi/2 或减去 pi/2 - 所以新的 theta 在 (x, y) 上产生新的方向。
但我怀疑一定有办法做到这一点,比我的更好。我可以单独检查每个屏幕限制(上、左、右、下)theta 和 increment/decrement 的值,以产生 pi/2 弹跳。但这将导致一堆 if()
语句,我相信必须有一个聪明的方法来实现这一点。
我的密码是
ball.x += ball.vel * cos(ball.theta);
ball.y += ball.vel * sin(ball.theta);
if( (ball.x + ball.radius) >= window.width || (ball.x - ball.radius) <= 0
|| (ball.y + ball.radius) >= window.height || (ball.y - ball.radius) <= 0) {
ball.theta += M_PI / 2;
但这不是很好用。它确实有一些弹跳,但在某些时候(大约 4 次弹跳后)它无法按照我需要的方式弹跳。
这是我的结构:
typedef struct {
double x;
double y;
double theta;
double vel;
double dt;
} Ball;
其中theta
代表给它方向的角度,dt
还没有使用,vel
是它的速度,现在是恒定的。
有什么方法可以让我使用三角学以一种智能的方式进行这种弹跳,并且减少 cpu 的努力吗?
编辑:将加法从度数更改为弧度。
但它仍然表现不佳。它像预期的那样弹跳了几次,我现在可以看到它无缘无故地弹回并沿着相反的轨迹。 (好像当时转了180度)
发送到 sin 和 cos 函数的天使需要以弧度为单位。
你的逻辑好像不对。垂直碰撞球速度应从垂直轴反映,水平碰撞球速度应从 hor 反映。轴:
if ((ball.x + ball.radius) >= window.width || (ball.x - ball.radius) <= 0)
ball.theta = M_PI - ball.theta;
else
if ((ball.y + ball.radius) >= window.height || (ball.y - ball.radius) <= 0)
ball.theta = - ball.theta;
如果你总是打开 PI/2。当从 sum
的 cos() 或 sin() 的三角公式
new_dx = vel*cos(theta + PI/2) = vel * (-sin(theta)) = -old_dy;
new_dy = vel*sin(theta + PI/2) = vel * cos(theta) = old_dx;
或
new_dx = vel*cos(theta - PI/2) = vel * sin(theta) = old_dy;
new_dy = vel*sin(theta - PI/2) = vel * (-cos(theta)) = -old_dx;
但是使用绝对弹性碰撞并根据碰撞方向改变dx或dy的符号更简单。
我需要在绘图区域内移动对象。该物体随机移动,每当它撞到墙壁时它就会 pi/2 弹跳。 (比如'pong'比赛中的球)
这很容易使用两个增量 'dx' 和 'dy',当它与限制发生冲突时,我只需更改正确的符号。但是在这个上,我的物体在 vcos(theta) = x 和 vsin(theta) = y 之间移动。当它撞到墙上时,我需要 theta 在自身上加上 pi/2 或减去 pi/2 - 所以新的 theta 在 (x, y) 上产生新的方向。
但我怀疑一定有办法做到这一点,比我的更好。我可以单独检查每个屏幕限制(上、左、右、下)theta 和 increment/decrement 的值,以产生 pi/2 弹跳。但这将导致一堆 if()
语句,我相信必须有一个聪明的方法来实现这一点。
我的密码是
ball.x += ball.vel * cos(ball.theta);
ball.y += ball.vel * sin(ball.theta);
if( (ball.x + ball.radius) >= window.width || (ball.x - ball.radius) <= 0
|| (ball.y + ball.radius) >= window.height || (ball.y - ball.radius) <= 0) {
ball.theta += M_PI / 2;
但这不是很好用。它确实有一些弹跳,但在某些时候(大约 4 次弹跳后)它无法按照我需要的方式弹跳。
这是我的结构:
typedef struct {
double x;
double y;
double theta;
double vel;
double dt;
} Ball;
其中theta
代表给它方向的角度,dt
还没有使用,vel
是它的速度,现在是恒定的。
有什么方法可以让我使用三角学以一种智能的方式进行这种弹跳,并且减少 cpu 的努力吗?
编辑:将加法从度数更改为弧度。
但它仍然表现不佳。它像预期的那样弹跳了几次,我现在可以看到它无缘无故地弹回并沿着相反的轨迹。 (好像当时转了180度)
发送到 sin 和 cos 函数的天使需要以弧度为单位。
你的逻辑好像不对。垂直碰撞球速度应从垂直轴反映,水平碰撞球速度应从 hor 反映。轴:
if ((ball.x + ball.radius) >= window.width || (ball.x - ball.radius) <= 0)
ball.theta = M_PI - ball.theta;
else
if ((ball.y + ball.radius) >= window.height || (ball.y - ball.radius) <= 0)
ball.theta = - ball.theta;
如果你总是打开 PI/2。当从 sum
的 cos() 或 sin() 的三角公式new_dx = vel*cos(theta + PI/2) = vel * (-sin(theta)) = -old_dy;
new_dy = vel*sin(theta + PI/2) = vel * cos(theta) = old_dx;
或
new_dx = vel*cos(theta - PI/2) = vel * sin(theta) = old_dy;
new_dy = vel*sin(theta - PI/2) = vel * (-cos(theta)) = -old_dx;
但是使用绝对弹性碰撞并根据碰撞方向改变dx或dy的符号更简单。