用于反弹物体的三角学

时间:2016-01-15 00:08:11

标签: c++ user-interface math drawing trigonometry

我需要在绘图区域内移动一个对象。物体随机移动,每当它撞到墙壁时它就会发出π/ 2弹跳。 (就像“乒乓球比赛”中的球一样)

这很容易使用两个增量的' dx'并且' dy',当它与极限相撞时,我会改变正确的标志。但是在这一个上,我的物体通过v cos(theta)= x和v sin(theta)= y。当它撞到墙壁时我需要增加pi / 2或减去pi / 2本身 - 所以新的theta在(x,y)上产生新的方向。

但我怀疑必须有办法做到这一点,比我的好。我可以单独检查每个屏幕限制(向上,向左,向右,向下)theta的值和增量/减量,以便产生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度)

3 个答案:

答案 0 :(得分:0)

发送到sin和cos函数的角度需要是弧度而不是度数。

答案 1 :(得分:0)

你的逻辑似乎错了。随着垂直碰撞球的速度应从垂直轴反射并与水平碰撞球的速度应从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;

答案 2 :(得分:0)

如果你总是打开PI / 2。当来自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的符号。