【问题标题】:2D Projectile tracing path clarification2D 弹丸追踪路径说明
【发布时间】:2012-06-07 15:35:25
【问题描述】:

2D游戏中的弹道追踪问题:

假设:

我们做了一个简化的假设,即重力是恒定的并且没有风或阻力。弹丸的运动由以下方程给出:

x = x0 + v0t cos(theta)

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

其中 (x0, y0) 是初始位置,v0 是初始速度(仅幅度),theta 是排放角,g 是重力加速度。求解 v0t 的第一个方程并代入第二个方程,我们得到方程 [1]:

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

校准:

校准是根据实际弹丸确定 g 值的过程。为此,我们随机发射一个弹丸并捕获:

  1. 起点 (x0, y0)
  2. 目标向量 (v0, theta)
  3. 曲线上的一个随机点 (x1, y1)

将值代入方程 [1] 并求解 g,我们得到:

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

应用:

现在我们有了 g,我们可以将其代回方程 [1],现在可以使用该方程从任何起点和初始速度跟踪射弹的路径。 (这是我看不懂的部分)

g=5.89

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

初始速度 = 1-100

放电角度 = 0-360

如果重力加速度为 5.89(在此游戏),起始位置是0,0?

我是一个数学新手,所有这些东西都不是我在别处找到的粗体字,我一直在绞尽脑汁。请假设我什么都不知道。

【问题讨论】:

  • 我不确定我是否理解您的问题。在顶部,您给出了足以绘制弹丸路径的参数路径方程(其中 x 和 y 是时间的函数)。您是否正在寻找抛物线本身的方程,即 y 作为 x 的函数?
  • 将所有常数代入方程 [1],得到一个简单的 y(x) 二次函数。那么你的问题是什么? (当然你必须选择一个初始速度和一个放电角度,因为每个都会给你不同的路径)
  • 谢谢霍华德,你好像知道你在说什么,你能留下来帮助我理解你在说什么吗?我按照你说的做了,得到了一个单一的答案。我不明白 y 的单个答案如何绘制抛物线,给定一个初始速度和一个放电角?
  • 在将所有内容放入 [1] 之后,还剩下 x 变量(您没有指定 x!),因此您有一个函数方程 y(x) = A * x^2 + B * x + C 和一些常量 @987654325 @、BC。所以你可以直接绘制y(x),它会显示路径。
  • 您所说的 x 变量是“起点”,对吧?

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


【解决方案1】:

选择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

可以直接绘制(y vs. x):see here

注意:我更正了重力的 - 符号。

【讨论】:

  • 你是如何得到 tan(theta) = 1.732 和 cos(theta) = 0.5 的?如果您将 60 插入 theta,例如 tan(60) 和 cos(60),我会得到不同的值
  • 编辑:这似乎是因为在谷歌中输入 tan(60) 会给你错误的答案,但它适用于我的计算器,非常感谢!!
【解决方案2】:

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

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

希望对你的努力有所帮助

【讨论】:

  • 你能给我一个穿过 x 线(或水平面)的抛物线(符合上述标准)的点,以便我可以对你所说的进行逆向工程吗?
  • 当然,因为穿过 x 轴,意味着 Y(t)=0 唱出你的初始方程组和条件 Y(0)=0 我们可以求解 t=-2*Vo*Sin( Theta)/g,这意味着 g 向下 (g0,t
【解决方案3】:

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

有初始条件:

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

因此,如果您将每一个集成一次 w.r.t.时间,你得到:

应用初始条件:

第二次积分给出:

再次应用初始条件:

进行替换可以得到你想要的最终方程,从枪响起,弹丸的 (u, v) 位置:

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

现在你有两个方程来表示弹丸的 (u, v) 位置。您可以插入弹丸的初始速度和枪的角度,从地平线测量为零,指向右侧。

您只需从零开始,选择时间增量,然后循环任意长的时间间隔。您将当前的时间值代入这些方程式,评估结果,增加时间,然后重复。

让我们想象一下,您将枪的角度与地平线逆时针旋转 45 度,并以 1000 英寸/秒的速度发射弹丸。您可以穿越时间,看到抛物线沿抛物线路径向上和向右移动,直到它到达顶点,然后开始回落到地平线。最终,您的 y 位移将回到零,然后继续进入负区域,就好像您是从悬崖边缘射出的一样。

如果你想知道弹丸在落地前走了多远,只需在高度小于或等于零时停止时间循环:

这是一个适合您的 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);
    }
}

那就是如何解决这个问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-23
    • 1970-01-01
    • 1970-01-01
    • 2017-08-18
    • 1970-01-01
    相关资源
    最近更新 更多