如何避免离合器台球?

0 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;
                }
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

Roo*_*ook 6

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

首先,这个:

vBalls[i]->angle = (float)-angle; 
vBalls[j]->angle = (float)angle; 
Run Code Online (Sandbox Code Playgroud)

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

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

for(unsigned int j = i + 1; j < BALL_COUNT; ++j)
Run Code Online (Sandbox Code Playgroud)

应该防止这种情况发生

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

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