如何避免离合器台球?

时间:2012-09-07 09:24:25

标签: c++ game-physics

我正在研究台球在相互碰撞中的简单行为。一切正常,但面对一些简单的球是一个问题是耦合球的效果,他们彼此凉爽。告诉我如何防止这种情况。

bool MGBilliard::CollisingBall(CCPoint curr_point, CCPoint next_point)
{
    float dx = next_point.x - (curr_point.x + dvdt.x);
    float dy = next_point.y - (curr_point.y - dvdt.y);
    float d = dx*dx+dy*dy;
    return d <= BALL_RADIUS * BALL_RADIUS;
}
double MGBilliard::angleCollisionBalls(Ball* current, Ball* next)
{
    double na;
    double dx = fabs(next->location.x - current->location.x);
    double dy = fabs(next->location.y - current->location.y);
    na = atan(fabs(dy/dx));
    if(atan(fabs(current->location.y/current->location.x)) < atan(fabs(next->location.y/next->location.x)))
        na = current->angle - na;
    else if(atan(fabs(current->location.y/current->location.x)) > atan(fabs(next->location.y/next->location.x)))
        na = current->angle + na;
    return na;
}
for(unsigned int i = 0;i<BALL_COUNT;++i)
    {
        if(vBalls[i]->speed > 0){
            vBalls[i]->speed += vBalls[i]->acceleration;
            float dsdt = vBalls[i]->speed*dt;
            dvdt.x = dsdt*cos(vBalls[i]->angle);
            dvdt.y = dsdt*sin(vBalls[i]->angle);
            vBalls[i]->location.x += dvdt.x;
            vBalls[i]->location.y += dvdt.y;
            for(unsigned int j = 1; j < BALL_COUNT; ++j)
            {
                if(i == j) continue;
                if(CollisingBall(vBalls[i]->spriteBall->getPosition(),vBalls[j]->spriteBall->getPosition()))
                {
                    vBalls[j]->speed = 600;
                    double angle;
                    angle = angleCollisionBalls(vBalls[i],vBalls[j]);
                    vBalls[i]->angle = (float)-angle;
                    vBalls[j]->angle = (float)angle;
                }
            }
        }
    }

1 个答案:

答案 0 :(得分:6)

通过快速查看代码,我会注意到两个直接的错误。

首先,这个:

vBalls[i]->angle = (float)-angle; 
vBalls[j]->angle = (float)angle; 

不是计算反角的正确方法。例如,当angle为零(或180度,就此而言)时,它不会执行您希望它执行的操作。

其次,您多次遍历整个vBalls数组,一次使用索引i,一个内部循环使用索引j。这意味着碰撞将被计算两次,并且两个球的speed将被设置为600!改变你的内循环:

for(unsigned int j = i + 1; j < BALL_COUNT; ++j)

应该防止这种情况发生。

还有一个更微妙的错误。您的碰撞检测不会考虑时间。每个球在游戏循环的每次迭代中移动特定距离。这意味着如果一个'tick'中没有发生碰撞,则球可以直接穿过另一个球,然后触发球远端的碰撞代码 。在这种情况下,您不能进行简单的基于半径的碰撞测试,就好像一个球的移动次数超过(BALL_RADIUS * BALL_RADIUS),您的系统会表现得很奇怪或根本不能正常工作。

我个人会使用向量来描述每个球的速度和方向,而不是角度和速度,但重构你的代码来做这个有点超出了这个问题的范围。