不断检查子弹是不是触及节点
Posted
技术标签:
【中文标题】不断检查子弹是不是触及节点【英文标题】:Constantly checking if a bullet has touched a node不断检查子弹是否触及节点 【发布时间】:2022-01-21 11:42:12 【问题描述】:我有一个非常简单的程序,您可以在其中使用您的 W、A、 S、D 和 space 键进行射击。所有的射击和移动动画都有效,但我不确定如何实现一个系统,在该系统中程序会不断检查子弹是否接触到一个节点,例如一个圆圈。
我在想我可以有一个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();
【问题讨论】:
【参考方案1】:您可以在提供给每个相关KeyValue
的自定义Interpolator
中使用Shape.intersect()
检查bullet
是否与other
相交。下面的片段将Interpolator
添加到shoot()
,但每个方向都需要一个相同的片段。该实现是线性的,简单地返回 t
不变,但您也可以查看 this 抛物线插值器。我还将other
设为类变量,shoot()
可以访问。我毫不迟疑地向空中发射了十几颗子弹。请注意,您不需要 start
值:“一个将是 synthesized 使用当时当前的目标值”播放动画。
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);
【讨论】:
【参考方案2】:您需要的是每次在游戏中绘制帧时都会检查碰撞的东西。计时器将在可以工作的单独线程中运行,但与游戏同步会困难得多。
【讨论】:
您可以使用AnimationTimer
在每一帧上执行代码,因为每帧只调用一次handle()
方法。
类似Timeline
,自定义Interpolator
会被周期性调用,如图here。【参考方案3】:
一般来说,当您必须“不断观察”OO 语言中的某些内容时,最好的解决方案是使用Observer pattern。
【讨论】:
以上是关于不断检查子弹是不是触及节点的主要内容,如果未能解决你的问题,请参考以下文章
我需要知道如何让 python 不断检查它是不是连接到互联网 [重复]