JavaFX Circle必须跟随光标 [英] JavaFX Circle must follow cursor

查看:71
本文介绍了JavaFX Circle必须跟随光标的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用JavaFX自己构建游戏.它具有一个必须跟随我的光标的圆(使用平滑的平移动画,因此它不会直接移到我的光标所在的位置)

I am trying to build a game myself using JavaFX. It features a circle that must follow my cursor (using a smooth translation animation, so it will not go directly to the location of my cursor)

到目前为止,我已经编写了这段代码

For now I have written this piece of code

    root.setOnMouseMoved(event -> {
        TranslateTransition tt = new TranslateTransition(Duration.millis(2000), circle);

        x[0] = event.getSceneX();
        y[0] = event.getSceneY();

        location.setText(x[0] + ", " + y[0]);

        if (x[0] != oldX[0] || y[0] != oldY[0]) {
            tt.stop();
            tt.setToX(event.getSceneX());
            tt.setToY(event.getSceneY());

            oldX[0] = x[0];
            oldY[0] = y[0];
        }

        tt.play();
    });

location.setText(..)只是一个标签,用于查看程序是否识别坐标.实际上,它们是:对于我的光标,每个像素移动都会立即更新这些数字.

The location.setText(..) is just a label to see whether the coords are recognized by the program. And in fact they are: for each pixel my cursor moves it updated these numbers instantly.

但是,我的圈子只会在其不动时移动到光标所在的位置.我希望形状也能随行随动,但不会.

However, my circle will only go to the location of my cursor when it does not move. I want the shape to follow my cursor on the go as well but it just won't.

所以我的问题是这样的:即使它在移动,如何使我的圈子跟随我的鼠标呢?

So my problem is this: how can I make my circle follow my mouse, even when it is moving?

推荐答案

使用 AnimationTimer 进行移动.您可能还想查看 Mike的博客中的用法示例.

Use an AnimationTimer for the movement. You may also want to check Mike's Blog about a usage example.

请阅读Daniel Shiffman的代码的本质,尤其是

Read The Nature of Code by Daniel Shiffman, especially the Chapter Vectors, 1.10 Interactivity with Acceleration. The webpage has a running example, easily to convert to JavaFX.

这是用JavaFX实现的书中的代码:

Here's the code from the book implemented in JavaFX:

Walker.java

Walker.java

import java.util.Random;

import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;

public class Walker extends Pane {

    private static Random random = new Random();

    PVector location;
    PVector velocity;
    PVector acceleration;
    float topspeed;

    double width = 30;
    double height = width;
    double centerX = width / 2.0;
    double centerY = height / 2.0;
    double radius = width / 2.0;

    Circle circle;

    public Walker() {

        location = new PVector(random.nextDouble() * width, random.nextDouble() * height, 0);
        velocity = new PVector(0, 0, 0);
        topspeed = 4;

        circle = new Circle(radius);
        circle.setCenterX(radius);
        circle.setCenterY(radius);

        circle.setStroke(Color.BLUE);
        circle.setFill(Color.BLUE.deriveColor(1, 1, 1, 0.3));

        getChildren().add(circle);

    }

    public void step(PVector mouse) {

        PVector dir = PVector.sub(mouse, location);
        dir.normalize();
        dir.mult(0.5);
        acceleration = dir;
        velocity.add(acceleration);
        velocity.limit(topspeed);
        location.add(velocity);

    }

    public void checkBoundaries() {

        if (location.x > Settings.SCENE_WIDTH) {
            location.x = 0;
        } else if (location.x < 0) {
            location.x = Settings.SCENE_WIDTH;
        }

        if (location.y > Settings.SCENE_HEIGHT) {
            location.y = 0;
        } else if (location.y < 0) {
            location.y = Settings.SCENE_HEIGHT;
        }
    }

    public void display() {
        relocate(location.x - centerX, location.y - centerY);
    }
}

Main.java

Main.java

import java.util.ArrayList;
import java.util.List;

import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class Main extends Application {

    Pane playfield;

    List<Walker> allWalkers = new ArrayList<>();

    PVector mouse = new PVector(0,0,0);

    @Override
    public void start(Stage primaryStage) {

        // create containers
        BorderPane root = new BorderPane();

        StackPane layerPane = new StackPane();

        // playfield for our walkers
        playfield = new Pane();

        layerPane.getChildren().addAll(playfield);

        root.setCenter(layerPane);

        Scene scene = new Scene(root, Settings.SCENE_WIDTH, Settings.SCENE_HEIGHT);
        primaryStage.setScene(scene);
        primaryStage.show();

        // add 1 walker
        addWalker();

        // capture mouse position
        scene.addEventFilter(MouseEvent.ANY, e -> {
            mouse.set(e.getX(), e.getY(), 0);
        });

        // process all walkers
        AnimationTimer loop = new AnimationTimer() {

            @Override
            public void handle(long now) {

                // move
                allWalkers.forEach((walker) -> walker.step(mouse));

                // check border
                allWalkers.forEach(Walker::checkBoundaries);

                // update in fx scene
                allWalkers.forEach(Walker::display);

            }
        };

        loop.start();

    }

    /**
     * Add single walker to list of walkers and to the playfield
     */
    private void addWalker() {

        Walker walker = new Walker();

        allWalkers.add(walker);

        playfield.getChildren().add(walker);

    }

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

Settings.java

Settings.java

public class Settings {

    public static double SCENE_WIDTH = 800;
    public static double SCENE_HEIGHT = 600;

}

PVector.java(您可以从处理"源代码中获取完整源代码)

PVector.java (you can get the full source from the Processing source code)

public class PVector {

    public double x;
    public double y;
    public double z;

    public PVector(double x, double y, double z) {
        super();
        this.x = x;
        this.y = y;
        this.z = z;
    }

    public void normalize() {
        double m = mag(); 
        if (m != 0 && m != 1) { 
          div(m); 
        } 
    }

    public void div(double value) {
        x /= value;
        y /= value;
        z /= value;
    }

    public void mult(double value) {
        x *= value;
        y *= value;
        z *= value;
    }

    public void add(PVector v) {
        x += v.x;
        y += v.y;
        z += v.z;
    }

    public void sub(PVector v) {
        x -= v.x;
        y -= v.y;
        z -= v.z;
    }

    public void limit(float max) {
        if (mag() > max) {
            normalize();
            mult(max);
        }
    }

    public double mag() {
        return Math.sqrt(x * x + y * y + z * z);
    }

    public static PVector sub(PVector v1, PVector v2) {
        return sub(v1, v2, null);
    }

    public static PVector sub(PVector v1, PVector v2, PVector target) {
        if (target == null) {
            target = new PVector(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
        } else {
            target.set(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
        }
        return target;
    }

    public void set(double x, double y, double z) {
        this.x = x;
        this.y = y;
        this.z = z;
    }
}

这篇关于JavaFX Circle必须跟随光标的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆