2D弹丸追踪路径澄清

时间:2012-06-07 15:35:25

标签: math geometry computational-geometry trigonometry projective-geometry

2D游戏中的弹丸追踪路径问题:

假设:

我们做出简化的假设,即重力是恒定的,没有风或阻力。射弹的运动由以下等式给出:

x = x0 + v0t cos(theta)

y = y0 + v0t sin(theta)+ .5 g t ^ 2

其中(x0,y0)是初始位置,v0是初始速度(仅大小),θ是放电角度,g是重力加速度。求解v0t的第一个等式并代入第二个等式,得到等式[1]:

y = y0 +(x-x0)tan(θ)+ .5(g / v0 ^ 2)(x-x0)^ 2 / cos(θ)^ 2

校准:

校准是确定实际射弹的g值的过程。为此,我们拍摄随机射弹并捕获:

  1. 起点(x0,y0)
  2. 目标向量(v0,theta)
  3. 曲线上的随机点(x1,y1)
  4. 将值代入等式[1]并求解g,我们得到:

    g =(v0 ^ 2)* {[2 cos(θ)^ 2(y1-y0)/(x1-x0)^ 2] - [sin(2θ)/(x1-x0)]}

    应用:

    现在我们有了g,我们可以将它替换回等式[1],它现在可用于从任何起点和初始速度追踪射弹的路径。 (这是我不理解的部分)

    G = 5.89

    (x0,y0)起始位置= 0,0

    初始速度= 1-100

    放电角度= 0-360

    有人可以解释如何获得抛物线的完整绘制路径,对于1-100之间的任何初始速度,以及0-360之间的任何放电角度,如果由于重力的加速度是5.89(在此游戏),起始位置是0,0?

    我是一个完整的数学新手,所有这些东西都不是我在其他地方找到的粗体字,并且一直在绞尽脑汁。请假设我一无所知。

3 个答案:

答案 0 :(得分:2)

你只会错过第一组方程中的时间 t和空间/时间约束,绘制抛射物的前x秒或直到射弹离开边界框m。 所以伪代码将是:

  • T = 0; x(0)=某个坐标; y(0)=另一个坐标
  • LOOP t
  • T = t + 1的
  • 计算坐标{X(t = 1),Y(t = 1)}
  • 绘制此点与前一点之间的点或线
  • LOOP UNTIL t>时间限制或点{X(t),Y(t)}在您的边界框之外

我希望在你的努力中有所帮助

答案 1 :(得分:2)

选择v0 = 10theta = 60 degrees我们

tan(theta) = 1.732
cos(theta) = 0.5

因此等式1读取(x0=0y0=0g=5.89已经给出了

y = 1.732*x - 0.1178*x^2

可以直接绘制(yx):see here

注意:我更正了-重力标志。

答案 2 :(得分:0)

这是一个非常简单的本科物理问题。你从牛顿定律的x和y方向开始:

force equilibrium in x-direction

force equilibrium in y-direction

初始条件:

x-displacement at time zero

x-velocity at time zero

y-displacement at time zero

y-velocity at time zero

其中Q是弹丸的初始速度,θ是指如果枪指向右侧,则从地平线逆时针测量的角度。

所以,如果你整合一次w.r.t.时间,你得到:

x-velocity versus time

y-velocity versus time

应用初始条件:

x-velocity constant

y-velocity constant

第二次整合给出:

x-displacement versus time

y-displacement versus time

再次应用初始条件:

x-displacement initial condition

y-displacement initial condition

进行替换时,从射击枪开始的那一刻起,为射弹的(u,v)位置提供了最终的方程式:

x-position of the projectile as a function of time

y-position of the projectile as a function of time

如果将坐标系的原点放在枪口出口处,则两个初始位移为零。

现在你有两个方程式用于射弹的(u,v)位置。您可以插入射弹的初始速度和从地平线处测量的枪的角度,指向右侧。

你只需要将时间从零开始,选择一个时间增量,并根据需要循环一段时间。您将当前时间值插入这些方程式,评估结果,增加时间并重复。

让我们想象一下,你将枪从地平线逆时针方向倾斜45度,并以1000英寸/秒的速度发射射弹。您可以通过时间逐步观察抛射物在抛物线路径中向上和向右移动,直到它到达其顶点,然后开始回落到地平线。最终你的y位移将返回到零,然后继续进入负值区域,就像你从悬崖边缘射击一样。

如果你想知道射弹撞击地面前的距离,只需在高度小于或等于零时停止时间循环:

time to fall back to earth

以下是适合您的Java实现:

package physics;

/**
 * CannonSimulator simulates shooting a projectile.  Users are responsible for making
 * sure that all constants use consistent units (e.g. meters for length, seconds for
 * time, kg for mass, etc.)
 * @author Michael
 * @since 6/14/12 9:47 PM
 * @link http://stackoverflow.com/questions/10935060/2d-projectile-tracing-path-clarification/11043389#11043389
 */
public class CannonSimulator {

    private double m;
    private double g;
    private double q;
    private double theta;

    public static void main(String[] args) {
        double m = ((args.length > 0) ? Double.valueOf(args[0]) : 1.0); // default mass is 1 kg
        double g = ((args.length > 1) ? Double.valueOf(args[1]) : 9.8); // default gravity is 9.8 m/sec^2
        double q = ((args.length > 2) ? Double.valueOf(args[2]) : 100.0); // default velocity is 100 m/sec
        double theta = ((args.length > 3 ? Double.valueOf(args[3]) : Math.PI/4.0)); // default angle is 45 degrees
        CannonSimulator simulator = new CannonSimulator(m, g, q, theta);
        double t = 0.0;
        double dt = 0.001; // time increment of 0.1 seconds
        while (simulator.v(t) >= 0.0) {
            System.out.println(String.format("time: %10.3f u: %10.3f v: %10.3f", t, simulator.u(t), simulator.v(t)));
            t += dt;
        }
    }

    public CannonSimulator(double m, double g, double q, double theta) {
        if (m <= 0.0) throw new IllegalArgumentException("mass must be greater than zero");
        if (g <= 0.0) throw new IllegalArgumentException("gravity must be greater than zero");
        if (q <= 0.0) throw new IllegalArgumentException("velocity must be greater than zero");

        this.m = m;
        this.g = g;
        this.q = q;
        this.theta = theta;
    }

    public double v(double time) {
        return time*(q*Math.sin(theta) - g*time/m);
    }

    public double u(double time) {
        return time*q*Math.cos(theta);
    }
}

那是如何解决这个问题。