Reputation: 1
The situation is described in the following picture : enter image description here
It's a simple game where I need to use "←" or "→" on the keyboard to move the player's brick,however when I do so the application's focus simply moved to the levelPane or the infoPane, is there any way to explicitly allow only the gamePane to receive keyboard input and the level pane will only be focused if I use my mouse and clicked on it?
Javafx code below:
public void start(Stage primaryStage) throws Exception{
FXMLLoader loader = new FXMLLoader(getClass().getResource("Game.fxml"));
Parent page = loader.load();
Scene scene = new Scene(page);
Pane levelPane = (Pane)loader.getNamespace().get("levelPane");
Pane gamePane = (Pane)loader.getNamespace().get("gamePane");
Pane infoPane = (Pane)loader.getNamespace().get("infoPane");
Button lv1 = (Button)loader.getNamespace().get("level1");
Button lv2 = (Button)loader.getNamespace().get("level2");
Button lv3 = (Button)loader.getNamespace().get("level3");
Button lv4 = (Button)loader.getNamespace().get("level4");
Button lv5 = (Button)loader.getNamespace().get("level5");
Label info = (Label)loader.getNamespace().get("info");
levelPane.setFocusTraversable(false);
infoPane.setFocusTraversable(false);
//gamePane.setFocusTraversable(true);
gamePane.requestFocus();
Circle ball = new Circle(10, Color.CADETBLUE);
ball.relocate(5, 5);
Rectangle playerBrick = new Rectangle(Data.PLAYER_BRICK_LENGTH,Data.PLAYER_BRICK_WEIGTH,Color.BLACK);
playerBrick.setArcWidth(20);
playerBrick.setArcHeight(20);
playerBrick.setX(150);
playerBrick.setY(350);
ArryList<Rectangle> breakableBricks = new ArryList<Rectangle>();
for (int i = 0; i < Data.BRICK_COUNT ; i++){
breakableBricks.add(new Rectangle(Data.B_B_LENGTH,Data.B_B_WEIGTH,Color.RED));
breakableBricks[i].setArcWidth(20);
breakableBricks[i].setArcHeight(20);
if(i%5 == 0){
pixelCountY += Data.B_B_WEIGTH + 10;
}
playerBrick.setX(pixelCountX);
playerBrick.setY(pixelCountY);
pixelCountX += Data.B_B_LENGTH + 10;
}
gamePane.getChildren().add(ball);
gamePane.getChildren().add(playerBrick);
gamePane.setBorder(new Border(new BorderStroke(Color.BLACK, BorderStrokeStyle.SOLID, CornerRadii.EMPTY, BorderWidths.DEFAULT)));
gamePane.setOnKeyPressed(new EventHandler<KeyEvent>(){
@Override
public void handle(KeyEvent event){
switch (event.getCode()){
case LEFT: goLeft = true;break;
case RIGHT: goRight = true;break;
}
}
});
gamePane.setOnKeyReleased(new EventHandler<KeyEvent>(){
@Override
public void handle(KeyEvent event){
switch (event.getCode()){
case LEFT: goLeft = false;break;
case RIGHT: goRight = false;break;
}
}
});
primaryStage.setScene(scene);
primaryStage.show();
Timeline timeline = new Timeline(new KeyFrame(Duration.millis(20),new EventHandler<ActionEvent>() {
double dx = Data.HORIZONTAL_VELOCITY; //Step on x or velocity
double dy = Data.VERTICAL_VELOCITY; //Step on y
double playerBrickSpeed = Data.PLAYER_BRICK_S;//Player Brick moving speed
@Override
public void handle(ActionEvent t) {
//move the ball
ball.setLayoutX(ball.getLayoutX() + dx);
ball.setLayoutY(ball.getLayoutY() + dy);
Bounds bounds = gamePane.getBoundsInLocal();
Bounds brickB = playerBrick.getLayoutBounds();
//If the ball reaches the left or right border make the step negative
if(ball.getLayoutX() <= (bounds.getMinX() + ball.getRadius()) ||
ball.getLayoutX() >= (bounds.getMaxX() - ball.getRadius()) ){
dx = -dx;
}
//If the ball reeaches the brick's wall makes the ball bounce
if(ball.getLayoutY() < brickB.getMaxY() & ball.getLayoutY() > brickB.getMinY()){
if(ball.getLayoutX() > brickB.getMinX() - Data.HORIZONTAL_VELOCITY & ball.getLayoutX() < brickB.getMinX() + Data.HORIZONTAL_VELOCITY || ball.getLayoutX() > brickB.getMaxX() - Data.HORIZONTAL_VELOCITY & ball.getLayoutX() < brickB.getMaxX() + Data.HORIZONTAL_VELOCITY ){
dx = -dx;
}
}
if(ball.getLayoutX() > brickB.getMinX() & ball.getLayoutX() < brickB.getMaxX()){
if(ball.getLayoutY() < brickB.getMaxY() + Data.VERTICAL_VELOCITY & ball.getLayoutY() > brickB.getMaxY() - Data.VERTICAL_VELOCITY || ball.getLayoutY() > brickB.getMinY() - Data.VERTICAL_VELOCITY & ball.getLayoutY() < brickB.getMinY() + Data.VERTICAL_VELOCITY){
dy = -dy;
}
}
//If the ball reaches the bottom or top border make the step negative
if((ball.getLayoutY() >= (bounds.getMaxY() - ball.getRadius())) ||
(ball.getLayoutY() <= (bounds.getMinY() + ball.getRadius()))){
dy = -dy;
}
//Moving the player's brick
if(goRight & brickB.getMaxX() < bounds.getMaxX() + Data.PLAYER_BRICK_S & goRight & brickB.getMaxX() < bounds.getMaxX() - Data.PLAYER_BRICK_S){
playerBrick.setX(playerBrick.getX() + Data.PLAYER_BRICK_S);
}
if(goLeft & brickB.getMinX() > bounds.getMinX() + Data.PLAYER_BRICK_S & goLeft & brickB.getMinX() > bounds.getMinX() - Data.PLAYER_BRICK_S){
playerBrick.setX(playerBrick.getX() - Data.PLAYER_BRICK_S);
}
}
}));
timeline.setCycleCount(Timeline.INDEFINITE);
timeline.play();
}
Upvotes: 0
Views: 941
Reputation: 2581
Can't help much unless you show your code but I think you should use GamePane.requestFocus()
or brick.requestFocus()
to make the GamePane
/brick
listen to your keyboard inputs.
According to the Javadoc for Node, the node.requestFocus() method
Requests that this Node get the input focus, and that this Node's top-level ancestor become the focused window.
Upvotes: 2