子弹轨迹

时间:2016-07-01 02:26:34

标签: java javafx

首先,我想用大炮射击一架飞机。 我已经为轨迹设置了这个时间轴,但是我没有在我的场景中看到子弹。我的轨迹代码很可能不正确。我试着在互联网上查看projectile motion的公式,但我对物理学一无所知;

import javafx.animation.Interpolator;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Bounds;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
import javafx.util.Duration;

public class Game_1 extends Application {

    private final double gravity = 9.81;
    private Timeline timeline;
    private ImageView plane;
    private Circle circle;
    private AnchorPane ap;

    @Override
    public void start(Stage primaryStage) {
        primaryStage.setTitle("Test");
        Group group = new Group();
        Scene scene = new Scene(group, 600, 350);
        scene.setFill(Color.BLACK);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private void shoot() {
        double x = 65.0f;
        double y = 408;
        double speed = 200;
        double t = 2;
        double angle = -45;
        double dx = Math.cos(angle) * speed;
        double dy = Math.sin(angle) * speed;
        circle = new Circle(x, y, 5, Color.BLACK);
        double x2 = x + dx * t;
        double y2 = (Math.tan(angle) * y - (gravity / (2 * Math.pow(speed, 2) * Math.cos(angle))) * Math.pow(x, 2));
        timeline = new Timeline();
        KeyValue xKV = new KeyValue(circle.centerXProperty(), x2);
        KeyValue yKV = new KeyValue(circle.centerYProperty(), y2, new Interpolator() {
            @Override
            protected double curve(double t) {
                return y + dy * t - 0.5 * gravity * t * t;
            }
        });
        KeyFrame xKF = new KeyFrame(Duration.seconds(t), xKV);
        KeyFrame yKF = new KeyFrame(Duration.seconds(t), yKV);
        timeline.getKeyFrames().addAll(xKF, yKF);
        ap.getChildren().add(circle);
        timeline.play();
        collision();
    }

    private void collision() {
        circle.boundsInParentProperty().addListener((ObservableValue<? extends Bounds> arg0, Bounds oldValue2, Bounds newValue2) -> {
            if (circle.getBoundsInParent().intersects(plane.getBoundsInParent())) {
                timeline.stop();
                ap.getChildren().remove(circle);
            }
        });
    }
}

1 个答案:

答案 0 :(得分:2)

The curve method应映射到[0, 1]区间。但是,您的方法会映射到更高的值。给定起始值val和结束值{{}的插补器t,从t0t1的动画时间i的值val0 1}}的计算方法如下:

val1

val = val0 + (val1 - val0) * i.curve((t - t0) / (t1 - t0)) 方法的参数是时间间隔中的相对位置(0 =动画开始; 1 =动画结束)。该方法的结果用于确定该值与结束值的接近程度(0 =仍处于起始值; 1 =处于结束值)。

因此,您应该计算炮弹曲线中的顶点curve(如here on Wikipedia所述)并使用不同的插补器:

hMax

请注意,向上移动意味着降低用户界面的Interpolator interpolator = new Interpolator() { @Override protected double curve(double t) { // parabola with zeros at t=0 and t=1 and a maximum of 1 at t=0.5 return 4 * t * (1 - t); } }; KeyValue yKV = new KeyValue(circle.centerYProperty(), hMax, interpolator); 坐标,因此在这种情况下,y小于 <{1>在开始时的值。

从那里开始,你的hMax方法永远不会被调用,并且某些字段未被初始化,如果被调用则会导致NPE。此外,如果这两个问题得到解决,黑色背景上的黑色圆圈很难看到......

实施例

请注意,这不是使用任何物理因素,而只是使用我选择的一些值:

y

请注意,shoot应该为参数0返回0,为参数1返回1.如果属性进一步动画,则其他任何内容都可能导致跳转。也许两部分的y运动会更合适,以防你想在动画结束后移动球。

插补器1: @Override public void start(Stage primaryStage) { Circle circle = new Circle(10); circle.setManaged(false); Pane pane = new Pane(circle); circle.setCenterX(20); circle.setCenterY(800); Timeline timeline = new Timeline(new KeyFrame(Duration.ZERO, new KeyValue(circle.centerXProperty(), 20), new KeyValue(circle.centerYProperty(), 800) ), new KeyFrame(Duration.seconds(3), new KeyValue(circle.centerXProperty(), 380), new KeyValue(circle.centerYProperty(), 10, new Interpolator() { @Override protected double curve(double t) { // parabola with zeros at t=0 and t=1 and a maximum of 1 at t=0.5 return 4 * t * (1 - t); } }) ) ); Scene scene = new Scene(pane, 400, 800); scene.setOnMouseClicked(evt -> timeline.playFromStart()); primaryStage.setScene(scene); primaryStage.show(); }
插值器2: Interpolator.curve

使用一半的时间间隔,每个时间间隔分别具有顶部的结束值和曲线的起始y坐标。