Bruno Battaglia Bruno Battaglia - 5 months ago 74
Java Question

Timeline for parabolic trajectory in JavaFX

I update the post. This is my final code. Now the problem is that I don't see the curve. Is it correct or does it means that the method is not calculating every single frame of the trajectory?

public void bulletMove() {
circle = new Circle();
circle.setRadius(8);
circle.setFill(Color.RED);
circle.setLayoutX(cannone_im.getLayoutX());
circle.setLayoutY(cannone_im.getLayoutY());
Duration t = Duration.seconds(5);
double speed = 100;
double t2 = (double) t.toSeconds();
double angle = Math.abs(cannone_im.getRotate());
angle = Math.toRadians(angle);
double dx = Math.cos(angle) * speed;
double dy = Math.sin(angle) * speed;
double x1 = 65.0f;
double y1 = 50.0f;
double x2 = x1 + dx * t2;
double y2 = y1 + dy * t2 - 0.5 * gravity * t2 * t2;
circle.setTranslateX(x1);
circle.setTranslateY(y1);
KeyValue xKv = new KeyValue(circle.translateXProperty(), x2);
KeyValue yKv = new KeyValue(circle.translateYProperty(), -y2);
kf = new KeyFrame(t,xKv,yKv);
timeline = new Timeline();
timeline.getKeyFrames().add(kf);
//SchermataGioco is my Scene
SchermataGioco.getChildren().add(circle);
timeline.play();
}

Answer

In a KeyValue, the first parameter should be a WritableValue, e.g. circle.centerXProperty(), which represents the initial coordinate, say x. The second parameter should be a type compatible value, in this case the x coordinate toward which the projectile should move. As the timeline plays, the WritableValue will be updated accordingly. Add a second KeyValue to drive the y coordinate.

In the first example seen here, three instances of KeyValue move a figure from it's initial position to its destination position, which is size units away along each coordinate axis. In this related example, a figure moves form point p1 to p2. In the example below, a Circle moves parallel to the x axis between 100 and 500. At the same time, the circle moves parallel to the y axis between 300 and 100 following the curve() defined by the parabola y = –4(x – ½)2 + 1, which has vertex (½, 1) and x intercepts at 0 and 1.

image

import javafx.animation.Interpolator;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
import javafx.stage.Stage;
import javafx.util.Duration;

/**
 * @see http://stackoverflow.com/a/38031826/230513
 */
public class Test extends Application {

    @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();
        Circle c = new Circle(100, 300, 16, Color.AQUA);
        Line l = new Line(100, 300, 500, 300);
        l.setStroke(Color.AQUA);
        group.getChildren().addAll(c, l);
        final Timeline timeline = new Timeline();
        timeline.setCycleCount(Timeline.INDEFINITE);
        timeline.setAutoReverse(false);
        KeyValue xKV = new KeyValue(c.centerXProperty(), 500);
        KeyValue yKV = new KeyValue(c.centerYProperty(), 100, new Interpolator() {
            @Override
            protected double curve(double t) {
                return -4 * (t - .5) * (t - .5) + 1;
            }
        });
        KeyFrame xKF = new KeyFrame(Duration.millis(2000), xKV);
        KeyFrame yKF = new KeyFrame(Duration.millis(2000), yKV);
        timeline.getKeyFrames().addAll(xKF, yKF);
        timeline.play();
    }

    public static void main(String[] args) {
        launch(args);
    }

}
Comments