0

I have a GameSceneController class that has an AnchorPane field, with the intention of assigning it to different 'Game Rooms'. I have a GamePaneController that is the controller for the FXML.

I am trying to make a custom 'sprite' class move inside of the nested anchorpane with arrow key presses. I can achieve it via button, but every time I press the arrow keys, it highlights the buttons in the scene root rather than moving the sprite within the pane.

Thanks!

Here is my code:

GameSceneController handling the 'outer' AnchorPane.

public class GameSceneController implements Initializable, SceneController {

    private GameController gc;
    private Sprite charSprite;
    private Scene menuScene;
    private Scene gameScene;
    private String[] panePaths = {"fxml/Room1.fxml", "fxml/Room2.fxml", "fxml/Room3.fxml"};
    private GamePaneController gPaneController;

    // testing
    int gCtr = 0;
    @FXML
    Button gCtrPress;
    @FXML
    Button nextRoomButton;
    @FXML
    AnchorPane gamePane;

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        gamePane.getChildren().add(new Region()); // this group
    }


    public void setMenuScene(Scene scene) {
        this.menuScene = scene;
    }
    public void setGameScene(Scene scene){
        this.gameScene = scene;
    }


    //   TESTING
    @FXML
    public void gCtrInc() {
        //gc.run(); //  TESTING
        if (gCtr < 2){
            gCtr++;
        } else {
            gCtr = 0;
        }
        System.out.println(gCtr);
    }
    //  TESTING

    @FXML
    public void openMenuScene(ActionEvent actionEvent) {
        Stage primaryStage = (Stage) ((Node) actionEvent.getSource()).getScene().getWindow();
        primaryStage.setScene(menuScene);
    }

    @Override
    public void setGameController(GameController gc) {
        this.gc = gc;
        setSprite();
    }
    public void setSprite(){
        this.charSprite = this.gc.getSprite();
    }

    @FXML
    public void setGamePane(ActionEvent actionEvent) throws IOException {
        FXMLLoader loader = new FXMLLoader(getClass().getClassLoader().getResource(panePaths[this.gCtr]));
        this.gamePane.getChildren().set(0, loader.load());
        gPaneController = loader.getController();
        gPaneController.setGameController(this.gc);
        gPaneController.setGameScene(this.gameScene);
        gCtrInc();
    }

    @FXML
    public void moveBtn(ActionEvent actionEvent){
        System.out.println("DEBUG: " +   ((AnchorPane)this.gamePane.getChildren().get(0)).getChildren());
        System.out.println(gPaneController.getSprite());
        gPaneController.getSprite().moveColumn(1);
    }

}

GamePaneController handling the 'nested' AnchorPane.

public class GamePaneController implements Initializable {

    private GameController gc;
    private Scene gameScene;
    private Sprite charSprite;

    @FXML
    AnchorPane gamePane;

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        System.out.println("DEBUG - Game Controller");
    }

    public void setGameScene(Scene scene){
        this.gameScene = scene;
        setUserKeyInput();
    }
    public void setUserKeyInput(){
        this.gamePane.setOnKeyPressed(e -> {
            e.consume();
            if (e.getCode() == KeyCode.UP) {
                this.charSprite.moveRow(-1);
            } else if (e.getCode() == KeyCode.DOWN) {
                this.charSprite.moveRow(1);
            } else if (e.getCode() == KeyCode.LEFT) {
                this.charSprite.moveColumn(-1);
            } else if (e.getCode() == KeyCode.RIGHT){
                this.charSprite.moveColumn(1);
            } else {};
        });
    }

    public void setGameController(GameController gc) {
        this.gc = gc;
        setSprite();
    }
    public void setSprite(){
        this.charSprite = this.gc.getSprite();
        this.gamePane.getChildren().add(this.charSprite);
    }

    public Sprite getSprite(){
        return this.charSprite;
    }
}

GameScene FXML

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

<?import javafx.scene.layout.AnchorPane?>

<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>

<AnchorPane
prefWidth="1080"            
prefHeight="720"
xmlns:fx="https://google.com/"
fx:controller="io.javasmithy.controller.scene.GameSceneController">
    <children>
        <AnchorPane fx:id = "gamePane" AnchorPane.leftAnchor="100" AnchorPane.topAnchor="100" prefHeight="600" prefWidth="800"/>
        <Label text="Game SCENE" fx:id="gameSceneTitle" AnchorPane.leftAnchor="310" AnchorPane.topAnchor="10"/>
        <Button fx:id="gCtrPress" text="inc Ctr" onAction="#moveBtn" AnchorPane.leftAnchor="800" AnchorPane.topAnchor="800"/>
        <Button fx:id="menuButton" text="mainMenu" onAction="#openMenuScene" AnchorPane.leftAnchor="10" AnchorPane.topAnchor="10"/>
        <Button fx:id="nextRoomButton" text="Next Room" onAction="#setGamePane" AnchorPane.leftAnchor="900" AnchorPane.topAnchor="600"/>
    </children>

</AnchorPane>

FXML for the 'nested' AnchorPane

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

<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<AnchorPane xmlns="http://javafx.com/javafx"
            xmlns:fx="http://javafx.com/fxml"
            fx:id="gamePane"
            fx:controller="io.javasmithy.controller.scene.GamePaneController"
            prefHeight="600.0" prefWidth="800.0"
            stylesheets="@/style/GamePaneStyle.css"
            styleClass="background">

    <children>
        <Label text="Room 1" AnchorPane.topAnchor="10" AnchorPane.leftAnchor="25"/>
    </children>

</AnchorPane>

Sprite Class in case you want to see it.

public class Sprite extends Rectangle{
    private static final Random random = new Random();
    int row;
    int column;

    PointGrid grid;

    public Sprite(PointGrid grid){
        super();
        this.grid = grid;
        this.row = 0;
        this.column = 0;
        setWidth(32.0);
        setHeight(32.0);
        setPos();
    }

    public void moveRow(int delta){
        if (row + delta < 0 || row + delta > this.grid.getHeight()-1) {
            return;
        } else {row+=delta;}
        setPos();
    }
    public void moveColumn(int delta){
        if (column + delta < 0 || column + delta > this.grid.getWidth()-1) {
            return;
        } else {column+=delta;}
        setPos();
    }
    private void setPos(){
        this.setX(grid.getPoint2D(row, column).getX());
        this.setY(grid.getPoint2D(row, column).getY());
    }

    public void moveRandomly(){
        int axis = random.nextInt(2);
        int direction = random.nextInt(2);
        int delta = 1;
        if (direction == 0) delta = -delta;
        if (axis ==0 ) {moveRow(delta);} else {moveColumn(delta);}
    }
}
Pierre
  • 23
  • 5
  • 1
    Without taking a in-depth look at this: Your sprite probably does not get the focus, but your `Button` does, since it's focus traversable. Any key events are delivered to the node that has the focus which means the event may only be observed on that node and it's ancestors and if teh event handler consumes the event, it may only be observable to event filters, not to event handlers... – fabian Apr 08 '20 at 05:38
  • Awesome, this worked! I setFocusTraversable(true) in my sprite constructor and I set the property false on the buttons and now the sprite is the only thing that responds. Thank you so much! – Pierre Apr 08 '20 at 14:24

0 Answers0