我写了一个程序,模拟一个50米的建筑物被抛出的球。 我通过在球撞击地面时反转y方向上的速度(y <0),保持水平速度相同,并将两个速度乘以某个最小值来增加碰撞检测,这样球最终会到达休息。
#include<stdio.h>
#include<math.h>
#include <stdlib.h>
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: %f x: %f y: %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
答案 0 :(得分:1)
如果没有输出任何内容,您可以在每个周期结束时尝试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);
}