简体   繁体   English

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

[英]How can I change the starting position of a node on PathTransition in JavaFX?

I'm learning about JavaFX by trying to build a (very) small platforming game. 我通过尝试构建(非常)小型平台游戏来学习JavaFX。 I thought it might be a good idea to simulate jumping by using PathTransition along an Arc shape. 我认为通过沿Arc形状使用PathTransition模拟跳跃可能是一个好主意。 Like this: 像这样:

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();
}

Event handler: 事件处理程序:

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

I discovered that doing this actually makes my figure jump BACKWARDS because the animation starts at the right end of the arc and ends at the left end. 我发现这样做实际上使我的图形向后跳,因为动画从弧的右端开始,到左端结束。 I tried looking through the documentation for Arc and PathTransition but couldn't find anything to help me solve the problem. 我尝试浏览有关ArcPathTransition的文档,但找不到任何能帮助我解决问题的方法。 What am I missing here? 我在这里想念什么?

The last two values you provide to the Arc constructor are the start angle and angular length of the arc (in degrees). 您提供给Arc构造函数的最后两个值是Arc的起始角度和角长度(以度为单位)。 Angles are measured relative to the positive x-axis in a counter-clockwise direction. 沿逆时针方向相对于正x轴测量角度。 So you are starting at 360 degrees (which of course is equivalent to 0 degrees: ie (centerX + radiusX, centerY) ) and heading counter-clockwise (up and left) for a half circle. 因此,您从360度开始(这当然等于0度:即(centerX + radiusX, centerY) ),然后逆时针(向上和向左)前进半圈。 To jump right, I think you want the start angle to be 180 and the angular length to be -180 (negative to rotate clockwise , a half-ellipse). 要向右跳,我想您希望起始角度为180 ,角度长度为-180 (负向顺时针旋转 ,为半椭圆形)。

Note the PathTransition moves the center of the node along the path, by changing its translateX and translateY properties. 注意, PathTransition通过更改节点的translateXtranslateY属性来沿路径移动节点的中心。 So to do a half-turn clockwise from the negative x-axis to the positive x-axis, you need centerX to be the initial horizontal center of the shape, plus the radiusX , and centerY to be the initial vertical center of the shape. 因此,要从负x轴到正x轴顺时针旋转半圈,需要将centerX作为形状的初始水平中心,再加上radiusXcenterY作为形状的初始垂直中心。

Here's a SSCCE that jumps the way you want (I think...). 这是一个SSCCE,它可以按照您想要的方式跳跃(我认为...)。 I used set methods on the Arc instead of the constructor, just for clarity as what each value is doing. 为了清楚起见,我在Arc而不是构造函数上使用了set方法,就像每个值在做什么一样。 You can achieve the same with the constructor if you prefer. 如果愿意,可以使用构造函数实现相同的效果。

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);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM