【问题标题】:Acceleration logic with Vector3Vector3的加速逻辑
【发布时间】:2017-02-23 20:31:07
【问题描述】:

我正试图让这个Vector3 在它向右时加速,在它不向右时减速。这是我的更新方法。为什么不加速?它具有恒定的速度。我知道您可以将 -5 添加到 vel.x 如果它在左侧,如果它在右侧添加 +5,然后在 vel.x 为 0 时停止它,但我正在努力完成这项工作。我真的不明白我做错了什么。

在课堂上我声明了两个Vector3s(用于update)

    public void update(float delta) {
        timePassed += Gdx.graphics.getDeltaTime(); //irrelevant

        if (pos.x > Kiwi.WIDTH / 2)
            vel.add(-5, 0, 0);

        vel.x *= 0.8f;

        vel.scl(delta);
        pos.add(vel.x, 0, 0);
        vel.scl(1 / delta);
    }

【问题讨论】:

  • 我只想要vel.add(-5,0,0); 中的if。没有其他的。当它向左时,我希望它再次减速。你还需要什么上下文?这是此屏幕自动取款机的完整更新方法。当vector 在屏幕的右半边时,我希望它加速,否则减速。我说得有道理吗?如果我不知道,请告诉我。
  • 如果我删除velx*=0.8f;,它会按预期加速,但显然它在到达屏幕中间后并没有减速,它会以恒定速度继续。
  • 抱歉拖了这么久。我非常感谢您的帮助。我更新了我的问题并包含了完整的更新方法。它目前的样子应该让它加速,对吧?请注意,ACC 等于 -3。
  • 抱歉,不清楚。第一次编辑是我在阅读您的答案后将更新方法更改为。我现在包含了更新方法,就像它从一开始的样子。
  • 在我的代码中,我使用的是 tutorialVel 和 tutorialPos,但为了更容易理解,我在这里分别将其更改为 vel 和 pos。在这里发布时,我忘记将单个 tutorialVel.x 错误地编辑为 vel.x。

标签: java libgdx logic game-physics


【解决方案1】:

新答案

public void update(float delta) {
    if (pos.x > Kiwi.WIDTH / 2)
        vel.add(-5, 0, 0);
    vel.x *= 0.8f;
    vel.scl(delta);
    pos.add(vel.x, 0, 0);
    vel.scl(1 / delta);
}

每帧调用一次更新方法。因此,上面的代码发生的情况是,您将每帧的速度降低 20%,这意味着如果您有 60FPS,当您位于左半边时,您将在一秒钟内将速度降低到 0.8^60 = 1.eE-6 或几乎为零屏幕。

您还想在向右时加速...向哪个方向加速?你现在所做的是,如果位置在屏幕的右半边,那么它会加速到左半边,这意味着一旦你到达右半边,它就会回到左半边!将-5 更改为+5,然后它会飞走,因为您将速度提高了5*60=300 px/s^2。您需要按时间增量缩放加速度。

此外,您还需要按时间增量来缩放减速。除以 delta (1/delta) 也没有任何意义,所以试试这个:

public void update(float delta) {
    if (pos.x > Kiwi.WIDTH / 2)
        vel.add(5*delta, 0, 0); // Acceleration is now 5 px/s^2 to the right
    vel.x -= vel.x*0.2f*delta; // Decay speed by 20% every second
    pos.add(vel.x*delta, 0, 0); // Move position by speed.
}

下面的旧答案

无需编写更多代码,我所能做的就是向您展示在一般情况下进行计算的正确方法。

如果您想使用欧拉方法求解运动 ODE,您可以这样做:

// Object state
speed = ...; // Unit is [m/s]
position = ...; // Unit is [m]   


// Inputs
frameDelta = ...; // Unit is [s]
acceleration = ...; // Unit is [m/s^2]

// Update step
speed += acceleration * frameDelta; // Unit [m/s^2 * s] = [m/s];
position += speed * frameDelta; // Unit [m/s * s] = [m] 

如果您希望速度“衰减”,您可以通过添加合适的减速(或拖动/风阻/摩擦力,随便你怎么称呼它)来实现:

decayRate = ...; // Unit is [m/(m*s^2) = 1/s^2] ((de)acceleration per meter)
acceleration -= speed * decayRate * frameDelta; // Unit is [m/s*1/s^2*s = m/s]

注意:您不存储加速度,而是从其他输入(键盘、鼠标、力、碰撞等)每帧计算它。

注意 2:欧拉法是最简单的求解器,可用于根据加速度计算位置和速度。它有一些问题,它不如 Runge-Kutta 准确,而且它还可能表现出一些与振荡有关的稳定性问题。

您知道当您看到某物卡在游戏中时像发疯一样摇晃吗?是的,这可能是欧拉的方法变得不稳定。

【讨论】:

  • 感谢您花时间帮助我。我想我现在解决了。
猜你喜欢
  • 2014-01-20
  • 1970-01-01
  • 1970-01-01
  • 2020-03-12
  • 1970-01-01
  • 1970-01-01
  • 2020-12-22
  • 1970-01-01
  • 2019-12-29
相关资源
最近更新 更多