我去年开始学习编码。虽然不是很好。 我试图用c语言绘制从地面射出的炮弹的轨迹。 (无论如何,我没有单独编码)。
(#对不起,我必须删除原始代码一段时间。如果您想查看原始代码,请告诉我。但我确定如果您只是完全足够请参阅下面的选定答案。)
如果我执行它,结果是这样的。
the speed is?
6
the angle is
32
the spring is
0.4
X=0.000000, Y=0.000000
X=0.000000, Y=-0.049000
X=0.000000, Y=-0.049000
X=0.000000, Y=-0.049000
X=0.000000, Y=-0.049000
X=0.000000, Y=-0.049000
X=0.000000, Y=-0.049000
X=0.000000, Y=-0.049000
X=0.000000, Y=-0.049000
X=0.000000, Y=-0.049000
我试图弄清楚我做错了什么,但我根本不知道。 请帮帮我!
答案 0 :(得分:4)
这种方法的问题是Y坐标可能变为负值。一旦它完成,如果初始速度不够高,球可能会卡在表面下方,如@RetiredNinja
的结果所示(坐标在-0.049
处被卡住了这是不正确的行为。)
原始代码的错误结果(不按比例缩放),修改后的参数:
球似乎"隧道"通过地面(一些值低于零)。
如何解决这个问题?我们需要正确地解决碰撞,确保球反弹而不是越过表面边界。为此,让我们在发生反弹的时间步长内检查球的行为。
垂直速度和垂直位置均为负时发生碰撞。要找到碰撞时间和速度,请使用运动方程:
一旦我们获得了碰撞速度,我们就可以简单地将新的垂直速度更新为-spring * vc
(spring
应该有更好的名称,例如coef_rest
);另一个好处是我们不再需要拨打pow
。
在时间步长期间可能会发生这种情况,因此我们需要在循环中执行此操作。另外需要注意的是,随着垂直速度衰减,弹跳变得无限频繁 - 所以我们需要一个"截止"阻止球弹跳的速度。
代码:
#include <stdio.h>
#include <math.h>
#ifndef M_PI
#define M_PI 3.141592654
#endif
int main()
{
const double g = 9.81; // gravity
const double dt = 0.025; // time step
const double maxtime = 5.0; // max time
const double spring = 0.95; // coefficient of restitution
const double cutoff = 1e-4; // cut-off velocity
double speed = 6;
double angle = 32;
angle = angle * M_PI / 180.0;
double init_vx = speed * cos(angle);
double init_vy = speed * sin(angle);
int springnumber = 0;
printf("0.0,0.0\n");
for (double ts = 0.0, vs = init_vy, time = dt; time <= maxtime;)
{
// positions *after* this time step
double px = time * init_vx;
double elapse = time - ts;
double py = 0.0, vy = 0.0;
if (vs >= cutoff)
{
py = (vs - 0.5 * g * elapse) * elapse;
vy = vs - g * elapse;
}
// check for bounce
if (vy < 0.0 && py < 0.0)
{
// collision time
double tc = 2.0 * vs / g;
// update speed after bounce and time of collision
springnumber++;
vs *= spring;
ts += tc;
continue;
}
// print
printf("%f,%f\n", px, py);
// timestep
time += dt;
}
return 0;
}
测试结果,参数与之前相同:
球不再是#34;隧道&#34;,这是正确的行为。