Java FX迷你高尔夫游戏 - 如何减慢移动球的速度

时间:2016-11-16 07:11:16

标签: animation javafx game-physics

我是初学者,并试图用Java FX创建一个简单的迷你高尔夫游戏。 我用线条建造了小型高尔夫球场。我从滑块获得关于击中强度的用户输入,并且可以使用键盘在8个不同方向上击中。

如果我点击按钮H,球开始向右移动。如果滑块值最小,它会缓慢移动,如果它的最大值,则移动得非常快。 但是我不能让运动减速直到它停止。

任何想法如何做到这一点?到目前为止,我的代码如下。

提前谢谢你!

package sample;

import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Slider;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
import javafx.stage.Stage;

public class Main extends Application {

    double directionx = 0;
    double directiony = 0;
    Line line1,line2,line3,line4,line5,line6,line7,line8,line9;

    @Override
    public void start(Stage primaryStage) throws Exception{

        primaryStage.setTitle("Minigolf");
        Pane pane = new Pane();
        Scene scene = new Scene(pane, 900, 600);
        pane.setStyle("-fx-background-color: green");
        primaryStage.setScene(scene);

        Slider slider = new Slider();
        slider.setMin(1);
        slider.setMax(10);
        slider.setValue(1);
        slider.setShowTickLabels(true);
        slider.setShowTickMarks(true);
        slider.setLayoutX(10);
        slider.setLayoutY(10);

        Circle ball = new Circle(10);
        Circle hole = new Circle(15);

        hole.setCenterX(75);
        hole.setCenterY(430);
        hole.setFill(Color.YELLOW);

        ball.setCenterX(100);
        ball.setCenterY(300);
        // creating golfcourse with lines
        line1 = new Line(50,200,500,200);
        line2 = new Line(50,350,650,350);
        line3 = new Line(50,200,50,350);
        line4 = new Line(500,200,500,50);
        line5 = new Line(650,350,650,200);
        line6 = new Line(500,50,800,50);
        line7 = new Line(800,50,800,500);
        line8 = new Line(800,500,50,500);
        line9 = new Line(50,500,50,350);

        pane.getChildren().addAll(slider,ball,hole,line1,line2,line3,line4,line5,line6,line7,line8,line9);


        new AnimationTimer() {
            @Override
            public void handle(long now) {

                    double ballY = ball.getCenterY();
                    double newballY = ballY + directiony;
                    // if ball touches vertical walls
                    if (ball.getBoundsInParent().intersects(line5.getBoundsInParent())
                            || ball.getBoundsInParent().intersects(line3.getBoundsInParent())
                            || ball.getBoundsInParent().intersects(line4.getBoundsInParent())
                            || ball.getBoundsInParent().intersects(line7.getBoundsInParent())
                            || ball.getBoundsInParent().intersects(line9.getBoundsInParent())) {
                        // changes direction
                        directionx = directionx * -1;
                    }
                    ball.setCenterX(ball.getCenterX() + directionx);
                    ball.setCenterY(newballY);
                    // if ball touches horizontal walls
                    if (ball.getBoundsInParent().intersects(line1.getBoundsInParent())
                            || ball.getBoundsInParent().intersects(line2.getBoundsInParent())
                            || ball.getBoundsInParent().intersects(line6.getBoundsInParent())
                            || ball.getBoundsInParent().intersects(line8.getBoundsInParent())) {
                        directiony = directiony * -1;
                    }
                    // if ball touches hole, then game is over
                    if (ball.getBoundsInParent().intersects(hole.getBoundsInParent())) {
                        System.out.println("Game over");
                        pane.getChildren().removeAll(ball);
                    }




            }

        }.start();

        // I get the slider value and making array where are 10 different strengts
        scene.setOnKeyPressed(event -> {
            double b = Math.round(slider.getValue());
            b--;
            int c = (int) b;
            double [] strengts = new double[10];
            double k = 0.1;
            for (int i = 0; i < strengts.length; i++) {
                strengts[i] = k;
                k = k + 0.5;
            }
            //  8 different directions to move the ball
            if (event.getCode().equals(KeyCode.H)) {
                directionx = directionx + strengts[c];
            }
            else if(event.getCode().equals(KeyCode.F)) {
                directionx = directionx - strengts[c];
            }
            else if(event.getCode().equals(KeyCode.V)) {
                directiony=directiony + strengts[c];
            }
            else if(event.getCode().equals(KeyCode.T)) {
                directiony= directiony - strengts[c];
            }
            else if(event.getCode().equals(KeyCode.B))
            {
                directionx = directionx + strengts[c];
                directiony = directiony + strengts[c];
            }
            else if(event.getCode().equals(KeyCode.Y))
            {
                directionx = directionx + strengts[c];
                directiony = directiony - strengts[c];
            }
            else if(event.getCode().equals(KeyCode.R))
            {
                directionx = directionx - strengts[c];
                directiony = directiony - strengts[c];
            }
            else if(event.getCode().equals(KeyCode.C))
            {
                directionx = directionx - strengts[c];
                directiony = directiony + strengts[c];
            }
        });
        primaryStage.show();
    }


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

2 个答案:

答案 0 :(得分:0)

只需使用物理学来摩擦。假设每帧的速度(v)保持不变。

球的能量(质量m):

E = 0.5 * m * v²

基于距离(s)行进的摩擦力和摩擦常数μ

ΔE = s * m * μ = Δt * v * m * μ

新能量为E - ΔE,你可以使用第一个公式来计算新的速度v'

0.5 * m * v'² = 0.5 * m * v² - s * m * μ
          v'² = v² - s * μ * 2
          v'  = sqrt(v² - s * μ * 2)

以上假设地面平坦。

这可以让你像这样降低速度:

@Override
public void start(Stage primaryStage) {
    Point2D direction = new Point2D(1, 1).normalize();
    Circle c = new Circle(10, 10, 10);

    Timeline tl = new Timeline();
    tl.getKeyFrames().setAll(new KeyFrame(Duration.seconds(1 / 60d), new EventHandler() {

        double speed = 3;
        double friction = 0.02;

        @Override
        public void handle(Event event) {
            double distance = speed;

            Point2D movement = direction.multiply(distance);
            c.setCenterX(c.getCenterX() + movement.getX());
            c.setCenterY(c.getCenterY() + movement.getY());

            double energyBefore = speed * speed;
            double energyLost = distance * friction;

            if (energyLost > energyBefore) {
                tl.stop();
                speed = 0;
                System.out.println("stopped");
            } else {
                speed = Math.sqrt(energyBefore - energyLost);
            }

        }
    }));

    tl.setCycleCount(Animation.INDEFINITE);

    Pane root = new Pane();
    root.getChildren().add(c);

    Scene scene = new Scene(root, 400, 400);
    scene.setOnMouseClicked(evt -> tl.play());

    primaryStage.setScene(scene);
    primaryStage.show();
}

答案 1 :(得分:0)

感谢您的回复,但作为初学者,我现在发现自己更简单的解决方案。

我只需添加4个if语句,如下所示:

if (directionx>0) {
                directionx = directionx - 0.01;
            }
if(directionx<0){
                directionx = directionx + 0.01;
            }
if(directiony>0) {
                directiony = directiony - 0.01;
            }
if(directiony<0) {
                directiony = directiony + 0.01;
            }

也许在实际的物理上它在某种程度上是错误的,但对我来说它看起来很真实。