不断检查子弹是否触及了节点

我有一个非常简单的程序,你可以使用你的WASD空格键进行拍摄。 所有的拍摄和移动动画都有效,但我不确定我是如何实现一个系统,在这个系统中,程序会不断检查子弹是否触及了一个节点,例如一个圆圈。

我以为我可以有一个ArrayList来存储所有子弹,然后使用TimerTask来检查子弹是否触及了一个节点; 但是我觉得这会减慢程序的速度,而且当TimerTask再次等待时,子弹也可以通过它们。

任何建议都会有帮助。

代码: Pastebin

 import javafx.application.Application; import javafx.stage.Stage; import javafx.scene.Scene; import javafx.scene.control.*; import javafx.scene.layout.Pane; import javafx.scene.shape.Circle; import javafx.animation.*; import javafx.util.Duration; public class functionalShooter extends Application { private String currentDirection = "W"; public static void main(String[] args){ launch(args); } @Override public void start(Stage stage) throws Exception{ Pane root = new Pane(); Scene scene = new Scene(root, 600, 400); stage.setScene(scene); stage.setResizable(false); stage.show(); Circle player = new Circle(10); player.setLayoutX(300); player.setLayoutY(200); Circle other = new Circle(100, 100, 10); root.getChildren().addAll(player, other); //key events scene.setOnKeyPressed(event -> { switch(event.getCode()){ case A: player.setLayoutX(player.getLayoutX()-10); currentDirection = "A"; break; case D: player.setLayoutX(player.getLayoutX()+10); currentDirection = "D"; break; case W: player.setLayoutY(player.getLayoutY()-10); currentDirection = "W"; break; case S: player.setLayoutY(player.getLayoutY()+10); currentDirection = "S"; break; case SPACE: if (currentDirection.equals("D")){ Circle newCircle = new Circle(player.getLayoutX()+10, player.getLayoutY(), 5); root.getChildren().add(newCircle); shoot(newCircle); } else if (currentDirection.equals("A")){ Circle newCircle = new Circle(player.getLayoutX()-10, player.getLayoutY(), 5); root.getChildren().add(newCircle); shoot(newCircle); } else if (currentDirection.equals("S")){ Circle newCircle = new Circle(player.getLayoutX(), player.getLayoutY()+10, 5); root.getChildren().add(newCircle); shoot(newCircle); } else { Circle newCircle = new Circle(player.getLayoutX(), player.getLayoutY()-10, 5); root.getChildren().add(newCircle); shoot(newCircle); } break; } }); } private void shoot(Circle bullet){ Timeline timeline = new Timeline(); if (currentDirection.equals("D")){ KeyValue start = new KeyValue(bullet.translateXProperty(), 0); KeyValue end = new KeyValue(bullet.translateXProperty(), 800); KeyFrame startF = new KeyFrame(Duration.ZERO, start); KeyFrame endF = new KeyFrame(Duration.seconds(10), end); timeline.getKeyFrames().addAll(startF, endF); } else if (currentDirection.equals("A")){ KeyValue start = new KeyValue(bullet.translateXProperty(), 0); KeyValue end = new KeyValue(bullet.translateXProperty(), -800); KeyFrame startF = new KeyFrame(Duration.ZERO, start); KeyFrame endF = new KeyFrame(Duration.seconds(10), end); timeline.getKeyFrames().addAll(startF, endF); } else if (currentDirection.equals("S")){ KeyValue start = new KeyValue(bullet.translateYProperty(), 0); KeyValue end = new KeyValue(bullet.translateYProperty(), 800); KeyFrame startF = new KeyFrame(Duration.ZERO, start); KeyFrame endF = new KeyFrame(Duration.seconds(10), end); timeline.getKeyFrames().addAll(startF, endF); } else{ KeyValue start = new KeyValue(bullet.translateYProperty(), 0); KeyValue end = new KeyValue(bullet.translateYProperty(), -800); KeyFrame startF = new KeyFrame(Duration.ZERO, start); KeyFrame endF = new KeyFrame(Duration.seconds(10), end); timeline.getKeyFrames().addAll(startF, endF); } timeline.setAutoReverse(false); timeline.setCycleCount(1); timeline.play(); } } 

您可以在提供给每个相关KeyValue的自定义Interpolator使用Shape.intersect()检查bulletother bullet相交。 下面的片段为shoot()添加了一个Interpolator ,但每个方向你需要一个相同的Interpolator 。 实现是线性的,只是返回t不变,但你也可以看看这个抛物线插值器。 我还创建了一个类变量,可以访问shoot() 。 我把十几颗子弹放到空中,没有明显的延迟。 请注意,您不需要起始值:“将使用播放动画时当前的当前值来合成一个起始值。

 private Circle other = new Circle(100, 100, 10); … else { KeyValue end = new KeyValue(bullet.translateYProperty(), -800, new Interpolator() { @Override protected double curve(double t) { if (!Shape.intersect(bullet, other).getBoundsInLocal().isEmpty()) { System.out.println("Intersection"); } return t; } }); KeyFrame endF = new KeyFrame(Duration.seconds(10), end); timeline.getKeyFrames().addAll(endF); } 

您需要的是每次在游戏中绘制框架时都会检查碰撞的内容。 计时器将在一个可以工作的单独线程中运行,但与游戏同步将更加困难。

通常,当你必须用OO语言“不断观察”某些东西时,最好的解决方案是使用Observer模式 。