Controllare costantemente se un proiettile ha toccato un nodo

Ho un programma molto semplice in cui puoi usare i tasti W , A , S , D e lo spazio per sparare. Tutte le animazioni di ripresa e movimento funzionano, ma non sono esattamente sicuro di come implementerei un sistema in cui il programma controlla costantemente se i proiettili hanno toccato un nodo, ad esempio un cerchio.

Stavo pensando che potrei avere un ArrayList per memorizzare tutti i proiettili e quindi usare un TimerTask per controllare se i proiettili hanno toccato un nodo; ma credo che rallenterebbe il programma, e anche il proiettile potrebbe passarli nel tempo in cui TimerTask è in attesa di tornare.

Qualsiasi suggerimento sarebbe d’aiuto.

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

È ansible verificare se il punto di intersezione interseca other utilizzando Shape.intersect() in un Interpolator personalizzato fornito a ciascun KeyValue pertinente. Il frammento di seguito aggiunge un Interpolator per shoot() , ma avrete bisogno di uno identico per ogni direzione. L’implementazione è lineare, semplicemente ritornando invariata, ma potresti anche guardare questo interpolatore parabolico. Ho anche creato other variabile di class, accessibile per shoot() . Ho messo in aria una dozzina di proiettili senza alcun ritardo percettibile. Si noti che non è necessario un valore start : “uno verrà sintetizzato utilizzando i valori target correnti al momento” viene riprodotta l’animazione.

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

Quello di cui hai bisogno è qualcosa che controlli la collisione ogni volta che disegni una cornice nel tuo gioco. Un timer verrebbe eseguito in un thread separato che potrebbe funzionare, ma sarebbe molto più difficile sincronizzarsi con il gioco.

In generale, quando è necessario “osservare costantemente” qualcosa in un linguaggio OO, la soluzione migliore è utilizzare il pattern Observer .