首先,我想用大炮射击一架飞机。 我已经为轨迹设置了这个时间轴,但是我没有在我的场景中看到子弹。我的轨迹代码很可能不正确。我试着在互联网上查看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);
}
});
}
}
答案 0 :(得分:2)
The curve
method应映射到[0, 1]
区间。但是,您的方法会映射到更高的值。给定起始值val
和结束值{{}的插补器t
,从t0
到t1
的动画时间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坐标。