如何在舞台内保持移动圈?

时间:2015-03-06 18:04:31

标签: java javafx geometry

所以我得到了这个代码,我试图让移动的圆圈在墙壁上反弹,这样他们就不会走出舞台了。我曾试图用moveCircle方法做到这一点,但我感觉真的超出了我的舒适区。

import javafx.animation.Animation.Status;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.geometry.Orientation;
import javafx.geometry.Rectangle2D;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollBar;
import javafx.scene.effect.Light;
import javafx.scene.effect.Lighting;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.BorderPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Screen;
import javafx.stage.Stage;
import javafx.util.Duration;

public class TimelineSample extends Application {

    Timeline timeline;

    private void init(Stage primaryStage) {
        double height = primaryStage.getHeight();
        double width = primaryStage.getWidth();
        BorderPane root = new BorderPane();
        primaryStage.setScene(new Scene(root, width, height));
        double radius = 30;
        Circle circle = new Circle(radius, radius, radius, Color.BLUE);
        Circle circle2 = new Circle(radius, radius, radius, Color.RED);
        Light.Distant light = new Light.Distant();
        light.setAzimuth(-135.0);
        Label label = new Label(
                "Space för starta spelet\nSpace för att pausa spelet\nTryck på cirklarna för att byta färg på dem");
        Label label2 = new Label("44");
        root.setStyle("-fx-background-color: green;");
        label2.setStyle(("-fx-padding : 100;"));
        root.setBottom(label2);
        root.setCenter(label);
        Screen screen = Screen.getPrimary();
        Rectangle2D bounds = screen.getVisualBounds();

        ScrollBar sbSpeed = new ScrollBar();
        sbSpeed.setMax(50);
        sbSpeed.setValue(25);
        sbSpeed.setOrientation(Orientation.VERTICAL);

        circle.opacityProperty().bind(sbSpeed.valueProperty().divide(30));
        circle2.opacityProperty().bind(sbSpeed.valueProperty().divide(30));
        sbSpeed.setOnScroll(e -> {
            circle.setTranslateX(+50);
        });

        circle.centerXProperty().bind(root.widthProperty().divide(2));
        circle.centerYProperty().bind(root.heightProperty().divide(2));
        circle.radiusProperty().bind(Bindings.min(root.widthProperty().divide(10),
                root.heightProperty().divide(10)));     

        circle2.centerXProperty().bind(root.widthProperty().divide(2));
        circle2.centerYProperty().bind(root.heightProperty().divide(2));
        circle2.radiusProperty().bind(Bindings.min(root.widthProperty().divide(10),
                root.heightProperty().divide(10)));     




        root.setTop(sbSpeed);

        primaryStage.setWidth(bounds.getWidth() * 0.40);
        primaryStage.setHeight(bounds.getHeight() * 0.40);

        Lighting lighting = new Lighting();
        lighting.setLight(light);
        lighting.setSurfaceScale(5.0);
        circle.setEffect(lighting);
        circle2.setEffect(lighting);
        timeline = new Timeline();
        timeline.setCycleCount(Timeline.INDEFINITE);
        timeline.setAutoReverse(true);
        timeline.getKeyFrames().addAll

        (new KeyFrame(Duration.ZERO, new KeyValue(circle.translateXProperty(),
                0)),
                new KeyFrame(new Duration(5000), new KeyValue(circle
                        .translateXProperty(), width - (radius * 2))));

        timeline.getKeyFrames().addAll(
                new KeyFrame(Duration.ZERO, new KeyValue(
                        circle2.translateYProperty(), 0)),
                new KeyFrame(new Duration(5000), new KeyValue(circle2
                        .translateYProperty(), height - (radius * 2))));
        timeline.play();
        root.getChildren().addAll(circle, circle2);
        boolean a = true;
        root.requestFocus();

        root.setOnKeyPressed(e -> {
            if (e.getCode().equals(KeyCode.SPACE)) {

                if (timeline.statusProperty().getValue().equals(Status.RUNNING)) {
                    timeline.pause();
                } else
                    timeline.play();
            }

        });

        circle.setOnMousePressed(event -> {

            if (circle.getFill().equals(Color.BLACK))

                circle.setFill(Color.YELLOW);
            else if (circle.getFill().equals(Color.BLUE))
                circle.setFill(Color.BROWN);
            else if (circle.getFill().equals(Color.YELLOW))
                circle.setFill(Color.BROWN);
            else if (circle.getFill().equals(Color.BROWN))
                circle.setFill(Color.BLACK);

            else
                circle.setFill(Color.BLUE);

        });

        circle2.setOnMousePressed(event -> {
            if (circle2.getFill().equals(Color.BLACK))

                circle2.setFill(Color.YELLOW);
            else if (circle2.getFill().equals(Color.BLUE))
                circle2.setFill(Color.BROWN);
            else if (circle2.getFill().equals(Color.YELLOW))
                circle2.setFill(Color.BROWN);
            else if (circle2.getFill().equals(Color.BROWN))
                circle2.setFill(Color.BLACK);

            else
                circle2.setFill(Color.BLUE);
            // }

        });
    }

    protected void moveCircle(Circle circle) {

             if (circle.getCenterX() < circle.getRadius() || 
                     circle.getCenterX() > circle.getCenterY() - circle.getRadius()) {
                 circle.translateYProperty(); 
            }
            if (circle.getCenterY() < circle.getRadius() || 
                    circle.getCenterY() > circle.getCenterX() - circle.getRadius()) {
                circle.translateXProperty();} 
            }






    public void pause() {
        timeline.pause();
    }

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

        init(primaryStage);
        primaryStage.show();

    }

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

    }

}

只需要启动球就可以了。

1 个答案:

答案 0 :(得分:0)

现在这是类似这样的通用伪代码,虽然不是特定于你的问题,但这是使这种“反弹”离开屏幕边缘的一般方法。

首先你需要5条信息,圆形速度(在x和y上,作为变量或向量2),圆形半径(或直径),圆形位置(在x和y上,作为变量或向量2) )和屏幕的宽度和高度。

此外,取决于圆的原点是否为中心(您将需要半径),左下角或左上角(您将需要直径)。在我的例子中,我们假设原点是在圆圈的中间爆炸。

一般的想法是这样的:

int windowWidth = 800, windowHeight = 600;
Circle c;

// Check if the left or right side of the circle leaves the screen bounds
// if so, reverse the velocity (mirror it)
if(c.x - c.radius < 0 || c.x + c.radius > windowWidth)
    c.velocityX = -x.velocityX;

// Check if the top or bottom side of the circle leaves the screen bounds
// if so, reverse the velocity (mirror it)
if(c.y - c.radius < 0 || c.y + c.radius > windowHeight)
    c.velocityY = -c.velocityY;

希望这是有道理的,这是检查圆是否通过屏幕边界并简单地镜像给定轴上的速度的情况。因此,如果球以5.0的速度(直接向右)移动然后超出窗口宽度,我们想要在x上取速度并取消它,所以现在速度变为-5,0(直接左)

这个问题的一个问题是线性外观,您可以轻松添加一些其他变量,如加速度,恢复原状,摩擦力和拖动力,以使其更逼真。