简体   繁体   中英

JavaFX smooth movement and timelines

I've recently started using JavaFX and I'm making a small game with a player being controlled by WASD keys. At first I made it so you could move the player by adjusting his x & y coordinates on keyPress but I found that the movement was very rough. Now I changed things and started using Timelines starting & stopping them when a key is pressed and released.

The code:

Timeline timelineW = new Timeline();
Timeline timelineA = new Timeline();
Timeline timelineS = new Timeline();
Timeline timelineD = new Timeline();

 public void createTimeLineW() {
    timelineW.setCycleCount(Timeline.INDEFINITE);
    final KeyValue kv = new KeyValue(player.yProperty(), -Integer.MAX_VALUE);
    final KeyFrame kf = new KeyFrame(Duration.hours(3000), kv);
    timelineW.getKeyFrames().add(kf);
}

public void createTimeLineA() {
    timelineA.setCycleCount(Timeline.INDEFINITE);
    final KeyValue kv = new KeyValue(player.xProperty(), -Integer.MAX_VALUE);
    final KeyFrame kf = new KeyFrame(Duration.hours(3000), kv);
    timelineA.getKeyFrames().add(kf);
}

public void createTimeLineS() {
    timelineS.setCycleCount(Timeline.INDEFINITE);
    final KeyValue kv = new KeyValue(player.yProperty(), Integer.MAX_VALUE);
    final KeyFrame kf = new KeyFrame(Duration.hours(3000), kv);
    timelineS.getKeyFrames().add(kf);
}

public void createTimeLineD() {
    timelineD.setCycleCount(Timeline.INDEFINITE);
    final KeyValue kv = new KeyValue(player.xProperty(), Integer.MAX_VALUE);
    final KeyFrame kf = new KeyFrame(Duration.hours(3000), kv);
    timelineD.getKeyFrames().add(kf);
}

This is the base of the current movement. So upon pressing W the imageView player would get timelineW.play() and upon releasing W it would get timelineW.stop(); and like so for the other keys. The overall reason I made this change was because the movement is more smooth but there are still several bugs. Is it possible to even do movement with this? Or should I look into alternatives.

Thanks on forehand.

Typically, you'll want to periodically check for a key and reset the movement Timeline:

/** Distance player moves in one "step." */
private static final int movementDistance = 10;

/** Time it takes to move one "step." */
private static final Duration movementTime = Duration.seconds(0.5);

private Timeline xMovement;

private void checkMovementKeys() {
    // ...

    if (xMovement == null) {
        xMovement = new Timeline();
    }

    if (rightMovementKeyPressed) {
        xMovement.getKeyFrames().setAll(
            new KeyFrame(movementTime,
                new KeyValue(player.xProperty(),
                    player.getX() + movementDistance)));
        xMovement.playFromStart();
    }
    if (leftMovementKeyPressed) {
        xMovement.getKeyFrames().setAll(
            new KeyFrame(movementTime,
                new KeyValue(player.xProperty(),
                    player.getX() - movementDistance)));
        xMovement.playFromStart();
    }

    // ...
}

Notice that the cycle count is left at its default, which is one.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM