实施碰撞检测

发布于 2024-11-10 09:11:38 字数 1608 浏览 3 评论 0原文

我编写了一个程序来模拟一个球从 50 米高的建筑物上扔下来。 我添加了碰撞检测,当球撞击地面时(y < 0)反转 y 方向的速度,保持水平速度相同,并将两个速度乘以某个最小值,以便球最终到达休息一下。

 #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

I wrote a program that will simulate a ball being thrown off a 50 meter building.
I added in collision detection by reversing the velocity in the y direction when the ball hits the ground (y < 0), keeping the horizontal velocity the same, and multiplying both velocities by some min value, so that the ball will ultimately come to a rest.

 #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;

 }

I am not getting the correct values needed to produce a correct graph of the data.
It could be because my conditions in the while loop need to be changed, or that I did not implement collision response correctly.

Here is also some sample data:

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

Picture of data plot

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

如果不输出任何内容,您可以在每个周期结束时尝试 fflush(fp) 。据我在您的代码中看到,您的物体在落地时会获得更快的速度,您必须将 vy = -(vy + ay*deltaTime*(.00001)) 更改为 vy = -(vy - ay*deltaTime*(.00001)) 来纠正它。如果每当 y y y y y y y y y y y y y y y 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 为负且 py 为正,因此我们可以假设当前的答案是

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

现在我们有 tc,即碰撞时间。因此,我们必须反转位置和速度的最后变化,然后只需步进时间 tc 秒,然后反转 vy 和步进 deltaTime - tc 秒即可完成该帧。所以在 if 条件内部就像这样(我可能在数学上遇到一些问题,所以如果万一你没有得到预期的结果,只需仔细检查所有方程):

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);
}

for not outputing anything you can try fflush(fp) at the end of each cycle. and as far as I can see in your code your object gets some more speed whenever it hits the ground you have to change vy = -(vy + ay*deltaTime*(.00001)) to vy = -(vy - ay*deltaTime*(.00001)) to correct it. you can also create a better implementation for collision if you calculate the exact time of collision whenever y < 0 and then move object down, change speeds, and move object up for the rest of cycle to have more realistic collision.

we know that deltaY = 1/2*ay*t^2 + vy*t so we can compute t using the folling formula :

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)

and since t has to be positive and knowing that ay is negetive and py is positive, we can assume the currect answer is

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

now we have tc which is time of collision. so we have to reverse the last changes in position and speed, then just step time tc seconds and then reverse vy and step deltaTime - tc seconds to complete that frame. so inside the if condition would be like (I just may have some problems doing the math, so if by any chance you didn't get expected results jsut doublecheck all equations):

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);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文