Reputation: 101
I am currently making a game in javafx, and what i need is to be able to make an image move left and right using mouse drag events, while the image is moving down. I have figured the latter part(the moving down part), and require assistance in adding the drag event to my image view object, so that on dragging it to the right is one event and dragging it to left is another event. Thank you in advance.
This is my fxml file
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/9.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.Controller">
<children>
<ImageView fx:id="player" fitHeight="42.0" fitWidth="98.0" layoutX="47.0" layoutY="27.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="@freefall.png" />
</image>
</ImageView>
<Button fx:id="button" layoutX="44.0" layoutY="21.0" mnemonicParsing="false" prefHeight="54.0" prefWidth="81.0" style="-fx-background-color: transparent; -fx-text-fill: transparent; -fx-border-fill: transparent;" text="Button" />
</children>
</AnchorPane>
This is my Controller Class
package application;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.animation.TranslateTransition;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.image.ImageView;
import javafx.util.Duration;
public class Controller implements Initializable {
@FXML
ImageView player;
TranslateTransition transition = new TranslateTransition();
private double startDragX;
private double startDragY;
@Override
public void initialize(URL arg0, ResourceBundle arg1) {
player.setOnMousePressed(e -> {
startDragX = e.getSceneX();
startDragY = e.getSceneY();
});
player.setOnMouseDragged(e -> {
double X = e.getSceneX();
if(X - startDragX > 0)
player.setTranslateX(5);
else if (X - startDragX < 0)
player.setTranslateX(-5);
});
//This code makes the player move downwards continuously
transition.setDuration(Duration.seconds(15));
transition.setNode(player);
transition.setToY(800);
transition.play();
}
}
The problem i am facing after changing the code is that the player moves, when you drag it once to the right. But when u again drag it to the right nothing happens, all I can do is drag it back to its original position (by dragging it back to the left).
Upvotes: 1
Views: 7365
Reputation: 8363
I think you already have the basics in your example.
There is something that I don't understand though: why is there a transition? If you want the ImageView
to follow your mouse cursor as you drag, then it would be weird to mix transition in (i.e. it would appear like a lag to users).
This is the basic way to move your ImageView
with drag event.
public class Controller implements Initializable {
@FXML
ImageView player;
private double startDragX;
private double startDragY;
@Override
public void initialize(URL arg0, ResourceBundle arg1) {
button.setMousePressed(e -> {
startDragX = e.getSceneX();
startDragY = e.getSceneY();
});
button.setMouseDragged(e -> {
button.setTranslateX(e.getSceneX() - startDragX);
button.setTranslateY(e.getSceneY() - startDragY);
});
}
}
Of course, you can choose to add the events in FXML and inject the event methods with @FXML
annotation.
After having understood the question, I think this is what you want (or at least almost). I assumed that you want to achieve an effect similar to "flick" on a touch mobile device, except that this is done with mouse.
public class Controller implements Initializable {
@FXML
ImageView player;
private static final double MIN_FLICK_PIXELS = 10;
private static final double FLICK_MOVEMENT = 5;
private enum Direction {
LEFT, RIGHT
}
private double lastXPosition;
private Direction lastFlickDirection = null;
TranslateTransition transition = new TranslateTransition();
@Override
public void initialize(URL arg0, ResourceBundle arg1) {
player.setOnMousePressed(e -> {
lastXPosition = e.getSceneX();
});
player.setOnMouseDragged(e -> {
double currentX = e.getSceneX();
// Detect as "right flick" if the previous flick direction is not right, and the dragged pixels is more than 10
if (lastFlickDirection != Direction.RIGHT && currentX - lastXPosition > MIN_FLICK_PIXELS) {
direction = Direction.RIGHT;
player.setTranslateX(player.getTranslateX() + FLICK_MOVEMENT);
lastXPosition = currentX;
}
// Detect as "left flick" if the previous flick direction is not left, and the dragged pixels is more than -10
else if (lastFlickDirection != Direction.LEFT && currentX - lastXPosition < -MIN_FLICK_PIXELS) {
direction = Direction.LEFT;
player.setTranslateX(player.getTranslateX() -FLICK_MOVEMENT);
lastXPosition = currentX;
}
});
player.setOnMouseReleased(e -> {
lastFlickDirection = null;
});
//This code makes the player move downwards continuously
transition.setDuration(Duration.seconds(15));
transition.setNode(player);
transition.setToY(800);
transition.play();
}
}
Doing this will:
One possible obvious flaw here is that the events are set on the ImageView
, so the events may be lost if the cursor goes outside the bounds of the ImageView
(it might not be lost, I didn't test this). If a problem occurs, shift the events out to perhaps its parent.
Upvotes: 2