实现碰撞检测

我写了一个程序,模拟一个50米的建筑物被抛出的球。 我通过在球撞击地面时反转y方向的速度(y <0),保持水平速度相同,并将两个速度乘以某个最小值,从而使球最终变为休息。

#include #include #include  int main() { FILE *fp; FILE *fr; float ax = 0, ay = 0, x = 0, y = 0, vx = 0, vy = 0; float time = 0, deltaTime = .001; float min = -.00000000001; int numBounces = 0; fr = fopen("input_data.txt", "rt"); fp = fopen( "output_data.txt", "w" ); if(fr == NULL){ printf("File not found");} if(fp == NULL){ printf("File not found");} fscanf(fr, "ax: %f ay: %fx: %fy: %f vx: %f vy: %f\n", &ax, &ay, &x, &y, &vx, &vy); while (vx > min && vy > min) { time = time + deltaTime; vx = vx + ax*deltaTime; vy = vy + ay*deltaTime; x = x + vx*deltaTime + (.5*ax*deltaTime*deltaTime); y = y + vy*deltaTime + (.5*ay*deltaTime*deltaTime); fprintf(fp, "%f\t%f\t%f\t%f\t%f\t%f\t%f\t\n", ax, ay, x, y, vx, vy, time); //Collision occurs; implement collision response if(y < 0) { vx = vx + ax*deltaTime*(.00001); vy = -(vy + ay*deltaTime*(.00001)); numBounces++; fprintf(fp, "%f\t%f\t%f\t%f\t%f\t%f\t%f\t\n", ax, ay, x, y, vx, vy, time); } } fclose(fp); fclose(fr); system ("PAUSE"); return 0; } 

我没有获得生成正确的数据图所需的正确值。 这可能是因为我需要更改while循环中的条件,或者我没有正确实现碰撞响应。

这里还有一些示例数据:

ax:0 ay:-9.8 x:0 y:50 vx:8.66 vy:5

数据图的图片

如果没有输出任何东西,你可以在每个循环结束时尝试fflush(fp) 。 并且就我在你的代码中看到的那样,你的对象在到达地面时会获得更高的速度你必须将vy = -(vy + ay*deltaTime*(.00001))更改为vy = -(vy - ay*deltaTime*(.00001))纠正它。 如果在y < 0时计算碰撞的确切时间,然后将对象向下移动,更改速度,并将对象移动到周期的其余部分以获得更逼真的碰撞,则还可以创建更好的碰撞实现。

我们知道deltaY = 1/2 * ay * t ^ 2 + vy * t所以我们可以使用以下公式计算t:

 assuming py is the current height of object(it's distance to ground) => -py = 0.5 * ay* t * t + vy * t => 0 = 0.5 * ay * t * t+ vy * t + py => t = (-vy +- sqrt(vy*vy - 2 * ay * py)) / (2 * ay) 

并且由于t必须是正的并且知道ay是negetive而py是正的,我们可以假设当前的答案是

 => tc = (sqrt(vy*vy - 2 * ay * py) - vy) / 2 / ay 

现在我们有tc这是碰撞的时间。 所以我们必须反转位置和速度的最后一次变化,然后只是步进时间tc秒然后反转vy并步进deltaTime - tc秒来完成那个帧。 所以在if条件下会是这样的(我可能在进行数学运算时遇到一些问题,所以如果你没有得到预期结果,那么jsut doublecheck所有方程式):

 if (y < 0) { float tc = (sqrt(vy*vy - 2 *ay * y)) / 2 / ay; x = x - vx*deltaTime - (.5*ax*deltaTime*deltaTime); y = y - vy*deltaTime - (.5*ay*deltaTime*deltaTime); vx = vx - ax * deltaTime; vy = vy - ay * deltaTime; vx = vx + ax * tc; vy = vy + ay * tc; x = x + vx*tc + (.5*ax*tc*tc); y = y + vy*tc + (.5*ay*tc*tc); vy = -(vy - ay*deltaTime*(.00001)); // you can also change above line and simply write // vy = vy * -0.99; // that will also create friction as you want it to be there vx = vx + ax * (deltaTime - tc); vy = vy + ay * (deltaTime - tc); x = x + vx* (deltaTime - tc) + (.5*ax* (deltaTime - tc)* (deltaTime - tc)); y = y + vy* (deltaTime - tc) + (.5*ay* (deltaTime - tc)* (deltaTime - tc)); numBounces++; fprintf(fp, "%f\t%f\t%f\t%f\t%f\t%f\t%f\t\n", ax, ay, x, y, vx, vy, time); }