首页 文章

游戏物理模拟:基于能量加速

提问于
浏览
-2

无数次我使用欧拉集成为小玩具游戏实现物理模拟:按箭头键设置加速度,然后整合加速度并加速度,然后积分速度并添加到位置以获得最终位置 . 我到处都看到了 .

但是当我想到动能时,我意识到这不是“现实的” . 如果给出类似汽车的东西,发动机产生功率(kW),而不是力/加速度 . 通过恒定加速,虚拟引擎的功率随着速度的增加而增加 . 在我的情况下,它是一艘宇宙飞船,但我想尝试在一个方向而不是恒定加速度上施加恒定功率 .

我的评估是否正确,跟踪能量比加速更真实?如果是这样,跟踪能量矢量而不是速度矢量实际上更有意义吗?但后来我必须转换为速度进行整合 . 所以我已经为一维模拟完成了这项工作,当然我可以使用E = 0.5 * m * v * v并求解v . 但是当使用向量时,我不能采用“平方根”能量(矢量) . 我可以找到方向相同的矢量,但幅度是原始的平方根,但物理上是否正确?

我当然肯定有人必须这样做,但我搜索并搜索网络并没有看到它 . 所以也许我不在基地 .

基本上,我想要做的是采用传统的“上升箭头和太空飞船以恒定加速度加速”并将其改为“向上推动箭头和宇宙飞船以恒定速率获得动能”,但是在2D情况下处理这种情况而不是1D案例(我已经有1D案例工作) .

更新:基于Exceptyon接受的答案的JavaScript代码:

function sq(x) {
    return x * x;
}

//Square cosine, preserving sign
function cos2(x) {
    var ret = Math.cos(x);
    if (ret >= 0) {
        return sq(ret);
    } else {
        return -sq(ret);
    }
}

//Square sine, preserving sign
function sin2(x) {
    var ret = Math.sin(x);
    if (ret >= 0) {
        return sq(ret);
    } else {
        return -sq(ret);
    }
}

function Ship() {
    this.x = 20; //m
    this.y = 40; //m
    this.dx = 0; //m/s
    this.dy = 0; //m/s
    this.ex = 0; //J
    this.ey = 0; //J
    this.pangle = Math.PI / 2; //pointing angle

    this.mass = 1; //kg
    this.power = 200; //W

    this.update = function(dt) {/*...*/} //update x/y based on dx/dy

    /**
     * Direct translation of Exceptyon's equations, but preserving sign in cos^2, sin^2 and sqrt
     * operations.
     * @param dt delta time in seconds
     */
    this.speedup2 = function(dt) {
        this.ex += this.power * dt * cos2(this.pangle);
        this.ey += this.power * dt * -sin2(this.pangle);
        var signx = this.ex > 0 ? 1 : -1;
        var signy = this.ey > 0 ? 1 : -1;
        this.dx = Math.sqrt(2 * Math.abs(this.ex) / this.mass) * signx;
        this.dy = Math.sqrt(2 * Math.abs(this.ey) / this.mass) * signy;
    };

    /**
     * Modified variation of Exception's post where I transform energy "vector" into velocity, that
     * I believe is equivalent.
     */
    this.speedup = function(dt) {
        this.ex += Math.cos(this.pangle) * this.power * dt;
        this.ey += -Math.sin(this.pangle) * this.power * dt;
        var totalEnergy = Math.sqrt(this.ex * this.ex + this.ey * this.ey);
        var speed = Math.sqrt(2 * totalEnergy / this.mass);

        var ratio = speed / totalEnergy;
        this.dx = this.ex * ratio;
        this.dy = this.ey * ratio;

        this.speed = Math.sqrt(this.dx * this.dx + this.dy * this.dy);
    };
}

1 回答

  • 1

    如果你愿意,你可以这样做,你只需跟踪沿x和y的动能(如果你在3d中移动,则需要跟踪z) .

    Ex = kinetic energy along x-axis
    Ey = kinetic energy along Y-axis
    //Etot = Ex + Ey
    //dt = 1/fps
    

    如果你不喜欢笛卡儿 Ex, Ey 你可以保留 Etot, direction ,那就完全相同了 . 转换将是:

    Ex = Etot * cos^2(direction)
    Ey = Etot * sin^2(direction)
    

    和逆:

    Etot = Ex + Ey
    direction = atan2(sqrt(Ey), sqrt(Ex))
    

    在给定的框架,你的引擎会给你Power * dt能量,就是这样

    \delta{Ex} = Power*dt * cos^2(direction)
    \delta{Ey} = Power*dt * sin^2(direction)
    

    从那里,你应该找到每一帧:

    //Etot = E_x + E_y
    //vtot = sqrt(2*Etot/m)
    v_x = sqrt(2*Ex/m) // = vtot*cos(direction)
    v_y = sqrt(2*Ey/m) // = vtot*sin(direction)
    

相关问题