【问题标题】:javaFX - creating smooth animation without creating a new ThreadjavaFX - 在不创建新线程的情况下创建流畅的动画
【发布时间】:2016-12-24 14:43:48
【问题描述】:

我的 javaFX 项目中有一辆汽车,当按下 SPACE 时,汽车(节点)的位置应该改变(汽车应该平稳跳跃)。所以我使用了一个事件处理程序,它调用一个名为 :moveUp()

的方法
scene.setOnKeyPressed(new EventHandler<KeyEvent>() {
        @Override
        public void handle(KeyEvent event) {
            switch (event.getCode())
            {
                case SPACE:
                    moveUp();
                    break;
            }
        }
    });

这会创建一个新的线程,其中汽车的速度会以 75 毫秒的间隔改变 10 次。

private void moveUp() {
   new Thread(new Runnable() {
       @Override
       public void run() {
           carSpeed = 10;
           for(;carSpeed>=0;carSpeed--)
           {
               try {
                   Thread.currentThread().sleep(75);
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
               carPosition_X+=carSpeed;
               carPosition_Y-=carSpeed;
               car.relocate(carPosition_X,carPosition_Y);
           }
           for(carSpeed=0;carSpeed<=10;carSpeed++)
           {
               try {
                   Thread.currentThread().sleep(75);
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
               carPosition_X+=carSpeed;
               carPosition_Y+=carSpeed;
               car.relocate(carPosition_X,carPosition_Y);
           }
       }
   }).start();
}

这段代码是这样的(按一次空格键跳车):

如果我不使用不同的线程,GUI 线程将被冻结,如果我不使用 Thread.sleep(),汽车会突然跳跃(不顺畅)。这段代码运行良好。但我了解到thread.start() 不能保证立即执行线程。如何保证立即执行?

【问题讨论】:

  • 据我所知,您不能保证立即执行,因为这是物理限制。但是:删除 Thread.sleep() 并使用每个循环执行中的增量时间来计算汽车应该移动的量。
  • 看看javafx.animation package; Timeline 可能是最合适的类...

标签: java animation javafx


【解决方案1】:

我建议留在 FX 应用程序线程中并使用 AnimationTimer 类。这是一个平滑跳跃的简短演示:

private void moveUp() {
        new AnimationTimer() {
            long startTime = -1;
            double initCarPosition_Y;                

            @Override
            public void handle(long now) {
                if(startTime == -1){
                    startTime = now;
                    initCarPosition_Y = carPosition_Y;
                    carSpeedX = 3d;
                    carSpeedY = -15d;                                   
                }                   

                double time = (now - startTime) / 1E9d;
                carPosition_X += carSpeedX * time;  
                carPosition_Y += carSpeedY * time;
                if(carSpeed > 0 && initCarPosition_Y <= carPosition_Y){
                    carPosition_Y = initCarPosition_Y;
                    stop();
                }
                carSpeedY += 0.8d * time; //gravity

                car.relocate(carPosition_X, carPosition_Y);                 
            }
        }.start();
}

这种方法让您可以完全直接地控制每一帧中发生的事情。但是,javaFX 还提供了高级动画类,包括预定义的插值器和转换。适合替代方法的可能是以下类:

  • PathTransition:允许您定义给定节点动画的点和曲线。
  • TimeLine:允许您根据节点位置等属性定义任意动画关键帧。

请注意,当您想要为用户控制的演员(如汽车)制作动画时,通常使用这些高级类可能会变得具有挑战性。这些类都需要一个确切的动画持续时间。例如,当你想翻译一个节点,只要按下一个特定的键,你事先并不知道动画的持续时间。

【讨论】:

    猜你喜欢
    • 2019-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-05
    • 1970-01-01
    • 2013-12-24
    相关资源
    最近更新 更多