JavaFx:在 运行 时检查 PathTransition 的当前位置

JavaFx: Check current position of PathTransition while running

我想通过 PathTransition 移动圆圈 (javafx.scene.shape.Circle) 的当前位置 (x,y),而过渡是 running/happening。

所以我需要某种任务,每 50 毫秒检查一次圆的位置(例如)。

我也试过 Stack Overflow 上建议的这个解决方案 Current circle position of javafx transition,但我似乎不适合我。

Circle projectile = new Circle(Playground.PROJECTILE_SIZE, Playground.PROJECTILE_COLOR);

root.getChildren().add(projectile);

double duration = distance / Playground.PROJECTILE_SPEED;

double xOff = (0.5-Math.random())*Playground.WEAPON_OFFSET;
double yOff = (0.5-Math.random())*Playground.WEAPON_OFFSET;

Line shotLine = new Line(player.getCurrentX(), player.getCurrentY(), aimLine.getEndX() + xOff, aimLine.getEndY() + yOff);

shotLine.setEndX(shotLine.getEndX() + (Math.random()*Playground.WEAPON_OFFSET));

PathTransition pt = new PathTransition(Duration.seconds(duration), shotLine, projectile);

// Linear movement for linear speed
pt.setInterpolator(Interpolator.LINEAR);

pt.setOnFinished(new EventHandler<ActionEvent>() {
    public void handle(ActionEvent event) {
    // Remove bullet after hit/expiration
    projectile.setVisible(false);
    root.getChildren().remove(projectile);
    }
});

projectile.translateXProperty().addListener(new ChangeListener<Number>() {

    @Override
    public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
    double x = collider.getTranslateX() - projectile.getTranslateX();
    double y = collider.getTranslateY() - projectile.getTranslateY();

    double distance = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));

    System.out.println("Distance: "+ distance);

    if (distance < 50) {
        System.out.println("hit");
    }
    }
});

pt.play();

A PathTransition 将通过操纵节点的 translateXtranslateY 属性来移动节点。 (TranslateTransition 的工作方式相同。)

很难明确回答你的问题,因为你的代码太不完整了,但是如果projectilecollider在场景图中有相同的parent,转换初始坐标projectilecollider 通过调用 localToParent 将给出 parent 中的坐标,包括翻译。因此,您可以观察 translateXtranslateY 属性并使用该转换来检查碰撞。如果它们有不同的 parent,您可以用 localToScene 做同样的事情,只需将两者都转换为相对于场景的坐标。

这是一个快速的 SSCCE。使用左右箭头瞄准,space射击:

import javafx.animation.Animation;
import javafx.animation.TranslateTransition;
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.BooleanBinding;
import javafx.geometry.Point2D;
import javafx.scene.Scene;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
import javafx.scene.transform.Rotate;
import javafx.stage.Stage;
import javafx.util.Duration;

public class ShootingGame extends Application {

    @Override
    public void start(Stage primaryStage) {
        final double width = 400 ;
        final double height = 400 ;

        final double targetRadius = 25 ;
        final double projectileRadius = 5 ;

        final double weaponLength = 25 ;

        final double weaponX = width / 2 ;
        final double weaponStartY = height ;
        final double weaponEndY = height - weaponLength ;

        final double targetStartX = targetRadius ;
        final double targetY = targetRadius * 2 ;;

        Pane root = new Pane();
        Circle target = new Circle(targetStartX, targetY, targetRadius, Color.BLUE);
        TranslateTransition targetMotion = new TranslateTransition(Duration.seconds(2), target);
        targetMotion.setByX(350);
        targetMotion.setAutoReverse(true);
        targetMotion.setCycleCount(Animation.INDEFINITE);
        targetMotion.play();

        Line weapon = new Line(weaponX, weaponStartY, weaponX, weaponEndY);
        weapon.setStrokeWidth(5);
        Rotate weaponRotation = new Rotate(0, weaponX, weaponStartY);
        weapon.getTransforms().add(weaponRotation);

        Scene scene = new Scene(root, width, height);
        scene.setOnKeyPressed(e -> {
            if (e.getCode() == KeyCode.LEFT) {
                weaponRotation.setAngle(Math.max(-45, weaponRotation.getAngle() - 2));
            }
            if (e.getCode() == KeyCode.RIGHT) {
                weaponRotation.setAngle(Math.min(45, weaponRotation.getAngle() + 2));
            }
            if (e.getCode() == KeyCode.SPACE) {

                Point2D weaponEnd = weapon.localToParent(weaponX, weaponEndY);

                Circle projectile = new Circle(weaponEnd.getX(), weaponEnd.getY(), projectileRadius);

                TranslateTransition shot = new TranslateTransition(Duration.seconds(1), projectile);
                shot.setByX(Math.tan(Math.toRadians(weaponRotation.getAngle())) * height);
                shot.setByY(-height);
                shot.setOnFinished(event -> root.getChildren().remove(projectile));

                BooleanBinding hit = Bindings.createBooleanBinding(() -> {
                    Point2D targetLocation = target.localToParent(targetStartX, targetY);
                    Point2D projectileLocation = projectile.localToParent(weaponEnd);
                    return (targetLocation.distance(projectileLocation) < targetRadius + projectileRadius) ;
                }, projectile.translateXProperty(), projectile.translateYProperty());

                hit.addListener((obs, wasHit, isNowHit) -> {
                    if (isNowHit) {
                        System.out.println("Hit");
                        root.getChildren().remove(projectile);
                        root.getChildren().remove(target);
                        targetMotion.stop();
                        shot.stop();
                    }
                });

                root.getChildren().add(projectile);
                shot.play();
            }
        });

        root.getChildren().addAll(target, weapon);

        primaryStage.setScene(scene);
        primaryStage.show();
    }

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