Handling Player Interactions
Overview
This section will introduce handling player interactions like clicking a button, changing game scenes, player movement, and mouse interactions as we add functionality to our menu and game scene.
- Create a new class in our
com. folder called "MenuController"
2. Set the FXML file controller to MenuContoller
| mainMenu.fxml |
|---|
| <?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Text?>
<?import javafx.scene.control.Button?>
<VBox xmlns:fx="http://javafx.com/fxml" fx:controller="com.javafxtutorial.javafxtutorial.MenuController">
<Text>JavaFX Tutorial</Text>
<Button>Start</Button>
<Button>Exit</Button>
</VBox>
|
3. Assign ID to text element
In order for us to change elements in our FXML file, we need to give the element an ID. We will be changing our text element, so let's give it an ID.
| mainMenu.fxml |
|---|
| <?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Text?>
<?import javafx.scene.control.Button?>
<VBox xmlns:fx="http://javafx.com/fxml" fx:controller="com.javafxtutorial.javafxtutorial.MenuController">
<Text fx:id="tutorialText">JavaFX Tutorial</Text>
<Button>Start</Button>
<Button>Exit</Button>
</VBox>
|
4. Create method to change text contents
Now we can go to our MenuController.java class and add a method to change our text:
| MenuController.java |
|---|
| package com.javafxtutorial.javafxtutorial;
import javafx.fxml.FXML;
import javafx.scene.text.Text;
public class MenuController {
@FXML
private Text tutorialText;
@FXML
protected void onStartButtonClick() {
tutorialText.setText("The text changed!");
}
}
|
Warning
The @FXML tag is required for any method that modifies an element in our FXML file.
- Assign
onAction for start button
Lastly, let's go back to our FXML file and tell our start button to use this method when we click it:
| mainMenu.fxml |
|---|
| <?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Text?>
<?import javafx.scene.control.Button?>
<VBox xmlns:fx="http://javafx.com/fxml" fx:controller="com.javafxtutorial.javafxtutorial.MenuController">
<Text fx:id="tutorialText">JavaFX Tutorial</Text>
<Button onAction="#onStartButtonClick">Start</Button>
<Button>Exit</Button>
</VBox>
|
Now run the application and click the start button, you should end up seeing this:
Loading A New Scene
Just having our text change when we click start is a bit boring, so let's change our method to load a new scene.
- Use start button to load an empty scene
First let's give our start button an ID:
| mainMenu.fxml |
|---|
| <?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Text?>
<?import javafx.scene.control.Button?>
<VBox xmlns:fx="http://javafx.com/fxml" fx:controller="com.javafxtutorial.javafxtutorial.MenuController">
<Text fx:id="tutorialText">JavaFX Tutorial</Text>
<Button onAction="#onStartButtonClick" fx:id="startButton">Start</Button>
<Button>Exit</Button>
</VBox>
|
Now we will change our method so that it uses the button to change the root of our scene to a empty group:
| MenuController.java |
|---|
| package com.javafxtutorial.javafxtutorial;
import javafx.fxml.FXML;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
public class MenuController {
@FXML
private Button startButton;
@FXML
protected void onStartButtonClick() {
startButton.getScene().setRoot(gameScreen());
}
private Group gameScreen() {
Group root = new Group();
return root;
}
}
|
Note
We gave our button an ID so that we could use it to get the scene it is in.
Now when we start our application and click the start button we should get an empty scene.

- Replace empty scene with FXML scene
Now let's create a FXML file for our game scene:
And let's modify our method to load this scene instead:
| MenuController.java |
|---|
| package com.javafxtutorial.javafxtutorial;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import java.io.IOException;
public class MenuController {
@FXML
private Button startButton;
@FXML
protected void onStartButtonClick() throws IOException {
startButton.getScene().setRoot(gameScreen().load());
}
private FXMLLoader gameScreen() {
return new FXMLLoader(getClass().getResource("game.fxml"));
}
}
|
Warning
Before running the application be sure to remove this line from game.fxml, or else the application will not run.
fx:controller="com.javafxtutorial.javafxtutorial.Game"
- Add exit functionality to exit button
Lastly, lets add a method for our exit button:
| MenuController.java |
|---|
| package com.javafxtutorial.javafxtutorial;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import java.io.IOException;
public class MenuController {
@FXML
private Button startButton;
@FXML
protected void onStartButtonClick() throws IOException {
startButton.getScene().setRoot(gameScreen().load());
}
private FXMLLoader gameScreen() {
return new FXMLLoader(getClass().getResource("game.fxml"));
}
@FXML
protected void onExitButtonClick() {
System.exit(0);
}
}
|
Make sure to tell our exit button to use the method as well:
| mainMenu.fxml |
|---|
| <?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Text?>
<?import javafx.scene.control.Button?>
<VBox xmlns:fx="http://javafx.com/fxml" fx:controller="com.javafxtutorial.javafxtutorial.MenuController">
<Text fx:id="tutorialText">JavaFX Tutorial</Text>
<Button onAction="#onStartButtonClick" fx:id="startButton">Start</Button>
<Button onAction="#onExitButtonClick">Exit</Button>
</VBox>
|
Player Movement
Now that our menu is set up, let's work on our game scene.
- Create a class called Game.
This is where we will handle our interaction and game logic.
Before we start with player movement, let's set up our game.fxml scene.
| game.fxml |
|---|
| <?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.Group?>
<?import javafx.scene.shape.Rectangle?>
<Group xmlns="http://javafx.com/javafx"
xmlns:fx="http://javafx.com/fxml"
fx:controller="com.javafxtutorial.javafxtutorial.Game">
<Rectangle height="100" width="100" fill="orange"/>
<Rectangle height="50" width="50" fill="blueviolet" fx:id="player"/>
</Group>
|
For now, our player will be represented by a blue rectangle with the id "player".
- Handle translating the player
To move our player we need to translate their X and Y positions when the player presses a key.
Let's set up 3 methods in our game class to help do this:
| Game.java |
|---|
| package com.javafxtutorial.javafxtutorial;
import javafx.animation.AnimationTimer;
import javafx.fxml.FXML;
import javafx.scene.shape.Rectangle;
public class Game {
private double velX;
private double velY;
@FXML
private Rectangle player;
@FXML
public void movementLoop() {
new AnimationTimer() {
@Override
public void handle(long now) {
player.setTranslateX(player.getTranslateX() + velX);
player.setTranslateY(player.getTranslateY() + velY);
}
}.start();
}
public void setVelX(double velX) {
this.velX = velX;
}
public void setVelY(double velY) {
this.velY = velY;
}
}
|
Our two methods setVelX and setVelY are where we set the player's X and Y velocity, while our movementLoop method handles translating the player using that velocity.
- Starting our movement loop
Before we can handle any keyboard inputs we need to start our movementLoop. To do this let's make some changes to our MenuController class.
| MenuController.java |
|---|
| package com.javafxtutorial.javafxtutorial;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import java.io.IOException;
public class MenuController {
@FXML
private Button startButton;
private static final int SPEED = 5;
@FXML
protected void onStartButtonClick() throws IOException {
FXMLLoader gameFXML = new FXMLLoader(getClass().getResource("game.fxml"));
Group gameRoot = gameFXML.load();
Scene currentScene = startButton.getScene();
currentScene.setRoot(gameRoot);
Game gameController = gameFXML.getController();
gameController.movementLoop();
gameRoot.requestFocus();
}
private FXMLLoader gameScreen() {
return new FXMLLoader(getClass().getResource("game.fxml"));
}
@FXML
protected void onExitButtonClick() {
System.exit(0);
}
}
|
To start, we've broken up our single line we used to change our Scene root into 4 lines.
Doing this allows us to use our game.fxml file separately, which we can use to access our Game class using this line: Game gameController = gameFXML.getController();
This allows us to start our movementLoop method we defined earlier.
Lastly, we request focus for our game window so that any keyboard inputs will be correctly recieved by our game.
- Handling keyboard inputs
Now that we've started our movement loop, we need to recieve keyboard input from the player so that we know when to change their position.
To do this we will use setOnKeyPressed and setOnKeyReleased to ensure smooth movement.
| MenuController.java |
|---|
| package com.javafxtutorial.javafxtutorial;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.input.KeyCode;
import java.io.IOException;
public class MenuController {
@FXML
private Button startButton;
private static final int SPEED = 5;
@FXML
protected void onStartButtonClick() throws IOException {
FXMLLoader gameFXML = new FXMLLoader(getClass().getResource("game.fxml"));
Group gameRoot = gameFXML.load();
Scene currentScene = startButton.getScene();
currentScene.setRoot(gameRoot);
Game gameController = gameFXML.getController();
gameController.movementLoop();
gameRoot.setOnKeyPressed(event -> {
if (event.getCode() == KeyCode.W) {
gameController.setVelY(-SPEED);
}
if (event.getCode() == KeyCode.S) {
gameController.setVelY(SPEED);
}
if (event.getCode() == KeyCode.A) {
gameController.setVelX(-SPEED);
}
if (event.getCode() == KeyCode.D) {
gameController.setVelX(SPEED);
}
});
gameRoot.setOnKeyReleased(event -> {
if (event.getCode() == KeyCode.W) {
gameController.setVelY(0);
}
if (event.getCode() == KeyCode.S) {
gameController.setVelY(0);
}
if (event.getCode() == KeyCode.A) {
gameController.setVelX(0);
}
if (event.getCode() == KeyCode.D) {
gameController.setVelX(0);
}
});
gameRoot.requestFocus();
}
private FXMLLoader gameScreen() {
// Group root = new Group();
// return root;
return new FXMLLoader(getClass().getResource("game.fxml"));
}
@FXML
protected void onExitButtonClick() {
System.exit(0);
}
}
|
Now when you run the application and press start you will be able to use the WASD keys to move the blue square around.
Mouse Interactions
The last type of player interaction we will handle is mouse interactions. For this we will use the orange rectangle we added to our scene previously.
- Assign an ID to the orange rectangle in
Game.fxml
| Game.fxml |
|---|
| <?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.Group?>
<?import javafx.scene.shape.Rectangle?>
<Group xmlns="http://javafx.com/javafx"
xmlns:fx="http://javafx.com/fxml"
fx:controller="com.javafxtutorial.javafxtutorial.Game">
<Rectangle height="100" width="100" fill="orange" fx:id="orangeRectangle"/>
<Rectangle height="50" width="50" fill="blueviolet" fx:id="player"/>
</Group>
|
2. Create methods for mouse interactions
We will be handling 3 different interactions with our orange rectangle in Game.java. Create 3 methods for this: mouseEnter, mouseExit, and click.
| Game.java |
|---|
| package com.javafxtutorial.javafxtutorial;
import javafx.animation.AnimationTimer;
import javafx.fxml.FXML;
import javafx.scene.shape.Rectangle;
public class Game {
private double velX;
private double velY;
@FXML
private Rectangle orangeRectangle;
@FXML
public void mouseEnter() {
orangeRectangle.setOpacity(0.5);
}
@FXML
public void mouseExit() {
orangeRectangle.setOpacity(1);
}
@FXML
public void click() {
orangeRectangle.setFill(Color.RED);
}
|
3. Assign methods to the orange rectangle
Lastly, we need to tell our rectangle to use these methods when we want it to.
| game.fxml |
|---|
| <?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.Group?>
<?import javafx.scene.shape.Rectangle?>
<Group xmlns="http://javafx.com/javafx"
xmlns:fx="http://javafx.com/fxml"
fx:controller="com.javafxtutorial.javafxtutorial.Game">
<Rectangle height="100" width="100" fill="orange" fx:id="orangeRectangle"
onMouseClicked="#click" onMouseEntered="#mouseEnter" onMouseExited="#mouseExit"/>
<Rectangle height="50" width="50" fill="blueviolet" fx:id="player"/>
</Group>
|
Success
Now when you run the application you should be able to hover over and click the orange rectangle to see the results.

Conclusion
Well Done! You've learned how to handle different types of player interactions. We covered:
- Adding functionality to buttons
- Changing scenes
- Smooth player movement
- Simple mouse interactions
Now it's time to move on to the last step, making this game your own with some customization!