简体   繁体   English

圆圈不动问题

[英]Circle not moving problems

So basically i am making a game in which the circle will move in the four directions.所以基本上我正在制作一个游戏,其中圆圈将在四个方向上移动。 When the "S" or "RIGHT" key is pressed once, the circle will move till it reaches the maxX of the pane.当按一次“S”或“RIGHT”键时,圆圈将移动,直到达到窗格的maxX。 And when i press the "A" key or "LEFT", the circle will move till it reaches minX of pane.当我按“A”键或“LEFT”时,圆圈会移动,直到到达窗格的 minX。 The "UP" or "W" and "DOWN" or "Z" keys also follow similar logic. “UP”或“W”和“DOWN”或“Z”键也遵循类似的逻辑。 If it get to maxY of pane it stops till another key is pressed and vice versa.如果它到达窗格的 maxY,它会停止,直到按下另一个键,反之亦然。

Here is the code for the controller class这是控制器类的代码

    @FXML
    private Pane board;

    private BooleanProperty wPressed = new SimpleBooleanProperty();
    private BooleanProperty aPressed = new SimpleBooleanProperty();
    private BooleanProperty zPressed = new SimpleBooleanProperty();
    private BooleanProperty sPressed = new SimpleBooleanProperty();

    private BooleanBinding keyPressed = wPressed.or(aPressed).or(zPressed).or(sPressed);

    


    private Circle circle = new Circle(20,40,20);




    private Rectangle[][] grid;
    private int size = 960;
    private int spots = 16;
    private int squareSize = size / spots;


    @FXML
    void handleB(ActionEvent event) {

    }

    AnimationTimer timer = new AnimationTimer() {

        double deltaX = 2;
        double deltaY = 2;
        
        @Override
        public void handle(long timestamp) {
            double rectX = circle.getLayoutX();
            Bounds bounds = board.getBoundsInLocal();


           

            double maxX = bounds.getMaxX();
            double maxY = bounds.getMaxY();
            double minX = bounds.getMinX();
            double minY = bounds.getMinY();

           

            if (circle.getLayoutX() >= ( maxX- circle.getRadius())) {
                deltaX = 0;
                //System.out.println(rect.getLayoutX());
            }
            if (circle.getLayoutY() >= (maxY - circle.getRadius())) {
                deltaY = 0;
            }


            if (circle.getLayoutX() <= ( minX + circle.getRadius())) {
                deltaX = 0;
                //System.out.println(rect.getLayoutX());
            }
            if (circle.getLayoutY() <= ( minY + circle.getRadius())) {
                deltaY = 0;
            }

            if(wPressed.get()) {
                circle.setLayoutY(circle.getLayoutY() - deltaY);
            }

            if(zPressed.get()){
                circle.setLayoutY(circle.getLayoutY() + deltaY);
            }

            if(aPressed.get()){
                circle.setLayoutX(circle.getLayoutX() - deltaX);
            }

            if(sPressed.get()){
                circle.setLayoutX(circle.getLayoutX() + deltaX);
            }



        }
    };


    @Override
    public void initialize(URL url, ResourceBundle resourceBundle) {

        
        grid = new Rectangle[spots][spots];
        for (int i = 0; i < size; i += squareSize) {
            for (int j = 0; j < size; j += squareSize) {
                Rectangle r = new Rectangle(i, j, squareSize, squareSize);
                grid[i / squareSize][j / squareSize] = r;
                // Filling each grid with the cell image
                r.setFill(Color.GRAY);
                r.setStroke(Color.BLACK);
                board.getChildren().add(r);
            }
        }

        board.getChildren().addAll(circle);


        movementSetup();

        keyPressed.addListener(((observableValue, aBoolean, t1) -> {
            if(!aBoolean){
                timer.start();
            } else {
                timer.stop();
            }
        }));




    }




    private void movementSetup() {
        board.setOnKeyPressed(e -> {
            if(e.getCode() == KeyCode.UP || e.getCode() == KeyCode.W ) {
                zPressed.set(false);
                sPressed.set(false);
                aPressed.set(false);
                wPressed.set(true);

            }

            if(e.getCode() == KeyCode.A || e.getCode() == KeyCode.LEFT) {
                zPressed.set(false);
                sPressed.set(false);
                wPressed.set(false);
                aPressed.set(true);
            }

            if(e.getCode() == KeyCode.Z || e.getCode() == KeyCode.DOWN) {
                wPressed.set(false);
                aPressed.set(false);
                sPressed.set(false);
                zPressed.set(true);
            }

            if(e.getCode() == KeyCode.S || e.getCode() == KeyCode.RIGHT) {
                wPressed.set(false);
                aPressed.set(false);
                zPressed.set(false);
                sPressed.set(true);
            }
        });


    }


}

** I did the pane in scenebuilder which i inserted it into an anchorpane as well** **我在scenebuilder中做了窗格,我也将它插入到锚窗格中**

The fxml file is below (ui.fxml) fxml 文件如下(ui.fxml)


<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.Pane?>

<AnchorPane maxHeight="1000.0" maxWidth="1200.0" minHeight="0.0" minWidth="0.0" prefHeight="1000.0" prefWidth="1200.0" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="fx.game.Controller">
   <children>
      <Pane fx:id="board" maxHeight="960.0" maxWidth="960.0" minHeight="0.0" minWidth="0.0" prefHeight="960.0" prefWidth="960.0">
         <children>
            <Button layoutX="367.0" layoutY="934.0" mnemonicParsing="false" onAction="#handleB" text="Button" />
         </children>
      </Pane>
   </children>
</AnchorPane>

Lastly the main class最后是主课


package fx.game;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

import java.io.IOException;

public class HelloApplication extends Application {
    @Override
    public void start(Stage stage) throws IOException {
        Parent root = FXMLLoader.load(getClass().getResource("ui.fxml"));
        stage.setTitle("Hello World");
        stage.setScene(new Scene(root));
        stage.show();
    }

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

Am really bad at game development I might be doing it completely wrong Anyone who can give me a better solution will be appreciated我在游戏开发方面真的很差我可能做错了任何能给我更好的解决方案的人将不胜感激

From my limited understanding and testing, board.setOnKeyPressed isn't responding to key events, I used the Scene instead.根据我有限的理解和测试, board.setOnKeyPressed没有响应关键事件,我使用了Scene You should also be taking into account onKeyReleased .您还应该考虑onKeyReleased

I don't know why you're starting and stoping the timer , just start it and on each, evaluate the state and make the changes that are required.我不知道您为什么要启动和停止timer ,只需启动它并在每个计时器上评估状态并进行所需的更改。

Your movement logic seems to be off as well.您的运动逻辑似乎也关闭了。 Get the circles current location, apply any movement to it as required, then determine if the new position is outside the acceptable bounds, adjust the position as needed and then update the circles position.获取圆的当前位置,根据需要对其进行任何移动,然后确定新位置是​​否超出可接受的范围,根据需要调整位置,然后更新圆的位置。

I also found that the Bounds the board would update based on the position of it's children, which made it hard to do bounds checking on, instead, I calculate the expected size based on the squareSize and the number of spots我还发现Bounds board会根据它的孩子的位置进行更新,这使得很难进行边界检查,相反,我根据squareSizespots计算预期大小

For example...例如...

import javafx.animation.AnimationTimer;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.beans.binding.BooleanBinding;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.geometry.Bounds;
import javafx.scene.Scene;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;

public class App extends Application {

    private BooleanProperty wPressed = new SimpleBooleanProperty();
    private BooleanProperty aPressed = new SimpleBooleanProperty();
    private BooleanProperty zPressed = new SimpleBooleanProperty();
    private BooleanProperty sPressed = new SimpleBooleanProperty();

    private BooleanBinding keyPressed = wPressed.or(aPressed).or(zPressed).or(sPressed);

    private Circle circle = new Circle(20, 20, 20);

    private Rectangle[][] grid;
    private int size = 960;
    private int spots = 16;
    private int squareSize = size / spots;
    AnimationTimer timer = new AnimationTimer() {

        double deltaX = 2;
        double deltaY = 2;

        @Override
        public void handle(long timestamp) {
            double rectX = circle.getLayoutX();
            Bounds bounds = board.getBoundsInLocal();

            double width = squareSize * spots;
            double height = squareSize * spots;

            double diameter = circle.getRadius() * 2;

            double x = circle.getLayoutX();
            double y = circle.getLayoutY();

            if (wPressed.get()) {
                y -= deltaY;
            }

            if (zPressed.get()) {
                y += deltaY;
            }

            if (aPressed.get()) {
                x -= deltaX;
            }

            if (sPressed.get()) {
                x += deltaX;
            }

            if (x >= (width - diameter)) {
                x = width - diameter;
            }
            if (x < 0) {
                x = 0;
            }

            if (y > (height - diameter)) {
                y = height - diameter;
            }
            if (y < 0) {
                y = 0;
            }

            circle.setLayoutX(x);
            circle.setLayoutY(y);

        }
    };

    private Pane board = new AnchorPane();

    @Override
    public void start(Stage stage) {
        stage.setTitle("Dice Game");

        setup();

        Scene scene = new Scene(board);
        movementSetup(scene);
        stage.setScene(scene);
        stage.sizeToScene();
        stage.show();
    }

    private void movementSetup(Scene scene) {

        scene.setOnKeyPressed(e -> {
            zPressed.set(false);
            sPressed.set(false);
            aPressed.set(false);
            wPressed.set(false);
            if (e.getCode() == KeyCode.UP || e.getCode() == KeyCode.W) {
                wPressed.set(true);
            } else if (e.getCode() == KeyCode.A || e.getCode() == KeyCode.LEFT) {
                aPressed.set(true);
            }else if (e.getCode() == KeyCode.Z || e.getCode() == KeyCode.DOWN) {
                zPressed.set(true);
            }else if (e.getCode() == KeyCode.S || e.getCode() == KeyCode.RIGHT) {
                sPressed.set(true);
            }
        });

    }

    protected void setup() {
        grid = new Rectangle[spots][spots];
        for (int i = 0; i < size; i += squareSize) {
            for (int j = 0; j < size; j += squareSize) {
                Rectangle r = new Rectangle(i, j, squareSize, squareSize);
                grid[i / squareSize][j / squareSize] = r;
                // Filling each grid with the cell image
                r.setFill(Color.GRAY);
                r.setStroke(Color.BLACK);
                board.getChildren().add(r);
            }
        }

        board.getChildren().addAll(circle);

        timer.start();
    }

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

}

nb: I'm a complete JavaFX noob, so there's probably better ways to approach this issue and maybe having a look at things like Introduction to JavaFX for Game Development (or other "javafx game development blogs" might provide better ideas nb:我是一个完整的 JavaFX 菜鸟,所以可能有更好的方法来解决这个问题,也许可以看看JavaFX 游戏开发简介(或其他“javafx 游戏开发博客”可能会提供更好的想法)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM