Kushagr Tyagi
Kushagr Tyagi

Reputation: 101

Moving an image using mouse drag events

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

Answers (1)

Jai
Jai

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.

Edit

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:

  • Shift the image 5 pixels to the right or left when user drag at least 10 pixels to the corresponding direction.
  • If the user drags 20 pixels continuously to the same direction, it only shift once.
  • If the user, within a single action, dragged 10 pixels to the right, then drag 10 pixels back to the left, the image will shift 5 pixels right, then 5 pixels left (which is original position).

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

Related Questions