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

时间:2016-08-27 20:09:22

标签: java javafx

我有一个非常简单的程序,您可以使用 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();
    }
}

3 个答案:

答案 0 :(得分:3)

您可以在提供给每个相关Shape.intersect()的自定义Interpolator中使用KeyValue检查bullet是否与other相交。下面的片段会将Interpolator添加到shoot(),但每个方向都需要一个相同的片段。实现是线性的,只是简单地返回t,但您也可以查看this抛物线插值器。我还为other提供了一个类变量,shoot()可以访问。我把十几颗子弹放到空中,没有明显的延迟。请注意,您不需要start值:“将使用”动画播放时当前的当前值“synthesized。{/ p>

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

答案 1 :(得分:0)

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

答案 2 :(得分:0)

一般来说,当你必须用OO语言“不断观察”某些内容时,最好的解决方案是使用Observer pattern