java - 如何更改 JavaFX 中 PathTransition 上节点的起始位置?

标签 java animation javafx

我通过尝试构建一个(非常)小型的平台游戏来学习 JavaFX。我认为沿着弧形使用 PathTransition 来模拟跳跃可能是个好主意。像这样:

import javafx.util.Duration;
import javafx.animation.PathTransition;
import javafx.scene.shape.Arc;

public void jump() {
    PathTransition jump = new PathTransition();
    Arc path = new Arc(
        figure().getX() + 20, //figure is a custom shape
        figure().getY() + figure().getHeight() / 2, 
        20, 80, 360, 180); 
    jump.setPath(path);
    jump.setNode(figure);
    jump.setAutoReverse(false);
    jump.setDuration(Duration.millis(3000));
    jump.setCycleCount(1);
    jump.play();
}

事件处理程序:

figure.setOnKeyPressed((e) -> {
    if (e.getCode() == KeyCode.SPACE) {
        jump();
    }
});

我发现这样做实际上会让我的人物向后跳跃,因为动画从弧线的右端开始,在左端结束。我尝试查看 Arc 的文档和 PathTransition但找不到任何东西可以帮助我解决问题。我在这里缺少什么?

最佳答案

您提供给 Arc 构造函数的最后两个值是弧的起始角度和角长度(以度为单位)。角度是相对于正 x 轴逆时针方向测量的。因此,您从 360 度(当然相当于 0 度:即 (centerX + radiusX, centerY))开始,逆时针(向上和向左)旋转半圈。要向右跳转,我认为您希望起始角度为 180,角长度为 -180(负值表示顺时针旋转,a半椭圆)。

请注意,PathTransition 通过更改其 translateXtranslateY 属性,沿路径移动节点的中心。因此,要从负 x 轴到正 x 轴顺时针旋转半圈,您需要将 centerX 作为形状的初始水平中心,加上 radiusX > 和 centerY 作为形状的初始垂直中心。

这是一个按照您想要的方式跳转的 SSCCE(我认为...)。我在 Arc 上使用了 set 方法而不是构造函数,只是为了清楚地了解每个值的作用。如果您愿意,您可以使用构造函数实现相同的目的。

import javafx.animation.PathTransition;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Arc;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Duration;

public class ArcTransitionTest extends Application {

    private final double xJumpRadius = 20 ;
    private final double yJumpRadius = 80 ;


    @Override
    public void start(Stage primaryStage) {
        Rectangle rect = new Rectangle(50, 200, 50, 100);
        rect.setFill(Color.CORNFLOWERBLUE);

        Button left = new Button("<");
        left.setOnAction(e -> jumpLeft(rect));

        Button right = new Button(">");
        right.setOnAction(e -> jumpRight(rect));

        HBox controls = new HBox(5, left, right);
        controls.setPadding(new Insets(10));
        controls.setAlignment(Pos.CENTER);

        Pane pane = new Pane(rect);
        BorderPane root = new BorderPane(pane, null, null, controls, null);
        primaryStage.setScene(new Scene(root, 600, 600));
        primaryStage.show();
    }

    private void jumpRight(Rectangle rect) {
        jump(rect, 180, -180, getHorizontalCenter(rect) + xJumpRadius, getVerticalCenter(rect));
    }

    private void jumpLeft(Rectangle rect) {        
        jump(rect, 0, 180, getHorizontalCenter(rect) - xJumpRadius, getVerticalCenter(rect));
    }

    private void jump(Rectangle rect, double startAngle, double angularLength, double centerX, double centerY) {
        Arc arc = new Arc();
        arc.setCenterX(centerX);
        arc.setCenterY(centerY);
        arc.setRadiusX(xJumpRadius);
        arc.setRadiusY(yJumpRadius);
        arc.setStartAngle(startAngle);
        arc.setLength(angularLength);

        PathTransition transition = new PathTransition(Duration.seconds(1), arc, rect);

        transition.playFromStart();
    }

    private double getHorizontalCenter(Rectangle rect) {
        return rect.getX() + rect.getTranslateX() + rect.getWidth() / 2 ;
        // Alternatively:
        // Bounds b = rect.getBoundsInParent();
        // return (b.getMinX() + b.getMaxX()) / 2 ;
    }

    private double getVerticalCenter(Rectangle rect) {
        return rect.getY() + rect.getTranslateY() + rect.getHeight() / 2 ;
        // Alternatively:
        // Bounds b = rect.getBoundsInParent();
        // return (b.getMinY() + b.getMaxY()) / 2 ;
    }

    public static void main(String[] args) {
        launch(args);
    }
}

关于java - 如何更改 JavaFX 中 PathTransition 上节点的起始位置?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30327580/

相关文章:

java - 如何在运行时在 Hibernate 中创建数据库?

java - 为什么我无法初始化通用参数和数组?

jQuery 动画按钮背景形状

javascript - 如何使用回调与 JavaScript 链接动画

css - 如何在javafx中设置边框间距

java - 无法从 Soap 响应中的节点检索文本内容

java - 如何绕过 JavaFX 的 TableView "placeholder"?

java - 为什么 Hibernate 插入带有外键的父行而不插入子行?

java - 在不使用多线程的情况下 Ping 多个 IP 地址

android - 如何为 View 的点击框设置动画?