【问题标题】:How do I stop my game ship from accelerating backwards?如何阻止我的游戏船向后加速?
【发布时间】:2019-10-03 22:00:18
【问题描述】:

我有一个游戏,它有一个船对象(带有 JavaFX 多边形)。当我用我的键(通过 EventHandlers 和 AnimationTimers)移动飞船时,它会向上移动。当我放手时,它应该将加速度变为-4,因此它不断从船的速度中带走-4,直到它假设达到0。但是,因为船可以向各个方向移动,所以速度有时是负的当船前进时。因此,当我试图在速度为负时停止船时,它不会发生,船一直向后移动。

当船的速度为负并向前移动时,我尝试了一些计算,但它有点太复杂了,我相信它不起作用。

这里是 Ship 计算速度 x 方法的代码:

AnimationTimer calculateVelocityX = new AnimationTimer() {
        @Override
        public void handle(long now) {
            if (getAcceleration() == 17)
                setVelocityX(getVelocityX() + (Math.cos(Math.toRadians(getRotation())) * (getAcceleration() * 0.01)));
            else if (acceleration == -4)
                setVelocityX(getVelocityX() + (Math.cos(Math.toRadians(getTempRotation())) * (getAcceleration() * 0.01)));
        }
    };
    AnimationTimer shipAccelerationTimer = new AnimationTimer() {
        @Override
        public void handle(long now) {
            getShipImage().setLayoutX(getShipImage().getLayoutX() + getVelocityX());
            getShipImage().setLayoutY(getShipImage().getLayoutY() - getVelocityY());
            wrapShip();
            if (getVelocityX() == 0 && getVelocityY() == 0) {
                getCalculateVelocityX().stop();
                getCalculateVelocityY().stop();
                setAcceleration(17);
                setCounterOne(0);
                setCounterTwo(0);
                setCounterThree(0);
                getShipAccelerationTimer().stop();
            }
        }
    };

此代码将使船向后移动,因为由于小数精度,速度实际上永远不会达到 0。但是,如果我说当速度小于 0 时,根据我上面所说的,这是不可能的。

货物沿指定方向移动时的速度标志图:

https://i.stack.imgur.com/5sxNi.png

因此,我不能只拥有“当速度小于 0 时”,因为就像在象限 2、3、4 中一样,我可以向前移动,但具有负 x、y 速度或两者兼而有之。

【问题讨论】:

  • 可以考虑使用<= 0?和/或将值四舍五入为Int
  • @kleopatra 我不喜欢泄露我的代码。对不起。希望我提供的代码就足够了。
  • @MadProgrammer
  • 对不起,我的意思是我不喜欢把我所有的代码都泄露出去,你说得对。如果我没有提供太多代码,我可以回答如何解决它。如果有的话,最好有代码解决方案。
  • 请查看代表速度符号的图像的新编辑。

标签: java animation javafx


【解决方案1】:

向后加速是行不通的,因为方向不是恒定的。

考虑这样一种情况,即船舶向上加速,然后在加速后但在停止之前转向右侧正好 90°。 y方向的部分速度分量永远不会变成0,但是x方向的运动方向会不断变化……

如果没有加速,您需要向与当前运动相反的方向减速,而不是根据您的船当前面向的方向这样做。

顺便说一句,我建议不要在这里使用 3 个注释来改变速度。这只会使您的代码变得不必要地复杂。您可以在一个动画中完成所有操作。

示例:

(代码保持简单而不是精心设计)

@Override
public void start(Stage primaryStage) throws Exception {
    double w = 600;
    double h = 600;

    Rotate rotation = new Rotate(0, 0, 0);
    Line ship = new Line(0, 0, 20, 0);
    ship.getTransforms().add(rotation);

    ship.setLayoutX(w / 2);
    ship.setLayoutY(h / 2);

    Pane root = new Pane(ship);
    root.setPrefSize(w, h);

    class Animator extends AnimationTimer {
        // the current speed
        double vx;
        double vy;

        // the direction the ship is facing
        double directionX = 1;
        double directionY = 0;

        // the current acceleration magnitude
        double acceleration = 0;

        @Override
        public void handle(long now) {
            if (acceleration > 0) {
                // speed up in the direction the ship is currently facing
                vx += directionX * acceleration * 0.001;
                vy += directionY * acceleration * 0.001;

                acceleration -= 0.1;
            } else if (vx != 0 || vy != 0) {
                // decelerate
                double speed = Math.hypot(vx, vy);

                // constant deceleration opposite to velocity
                double correctionFactor = Math.max((speed - 0.01) / speed, 0);
                vx *= correctionFactor;
                vy *= correctionFactor;
            }

            // update position
            ship.setLayoutX(ship.getLayoutX() + vx);
            ship.setLayoutY(ship.getLayoutY() + vy);
        }

    }

    Animator animator = new Animator();
    animator.start();

    Scene scene = new Scene(root);

    // make sure the ship always faces the mouse
    root.setOnMouseMoved(evt -> {
        double dx = evt.getX() - ship.getLayoutX();
        double dy = evt.getY() - ship.getLayoutY();

        if (dx == 0 && dy == 0) {
            // handle special case of mouse being in the same position as the ship
            dx = 1;
        }

        // assign normalized direction
        double magnitude = Math.hypot(dx, dy);
        animator.directionX = dx / magnitude;
        animator.directionY = dy / magnitude;

        // update ship rotation
        rotation.setAngle(Math.toDegrees(Math.atan2(dy, dx)));
    });

    root.setOnMouseClicked(evt -> {
        // accelerate
        animator.acceleration = 17;
    });
    primaryStage.setScene(scene);
    primaryStage.show();
}

【讨论】:

  • 好的,谢谢。首先,我仍然不确定你的第二段。如果你能更详细地解释它,为什么 y 速度永远不会变为 0,谢谢。另外,我不明白为什么 directionX 是 1 而 directionY 是 0 来确定船的方向。另外,我不确定 Math.atan2 是如何工作的。除了我的问题,这完全解决了我的问题。
  • 任何加速度都不会改变与加速度正交的速度分量。如果您从未使用矢量来表示运动、位置和加速度,这有点难以解释。方向的初始值并不重要。但是,在这种情况下,它与线的方向相匹配。无论如何,只要鼠标在场景上移动,该方向就会被覆盖。至于atan2:通常您使用反正切 (atan) 来计算基于 y/x 的角度,但这样会丢失信息 (y/x == -y/(-x))。 atan2 负责这个...
  • (在这种情况下,y 和 x 是鼠标相对于船舶位置的位置。它只是一种计算使线面向鼠标所需的旋转角度的方法。)跨度>
  • 好吧,但是为什么你在实例化的时候特意设置了directionX = 1和directonY = 0呢?
  • 另外,如果你能回答一件事,我不明白这是如何工作的:双校正因子 = Math.max((speed - 0.01) / speed, 0)。为什么它被称为校正因子以及代码如何使船减速?非常感谢。
【解决方案2】:

如果我在你身边,我会考虑考虑速度与他的大小和方向,其中 Magnitude>=0 和方向为 ±1,与正 X 和正 Y 相比。

【讨论】:

  • 这有什么帮助?我必须在速度 X 和速度 Y 可能为负的任何方向上停下船。
  • 请查看代表速度符号的图像的新编辑。
  • @user12055579 如果 (V.Magnitude
  • 我仍然对如何在代码中实现这一点感到困惑,因为我不明白你的意思。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-03
  • 2022-11-25
  • 1970-01-01
  • 2013-11-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多