HIDE NAV

Java FX Breakout 2026

Part 2 - Paddle and Keyboard Input

In this Java FX Breakout update, we add a custom input handling object and paddle to control.

InputHandler.java


package ceccs;

import javafx.event.EventHandler;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;


public class InputHandler {
    JfxBreakoutApp app;

    //TODO: add the mouse controls next session
    EventHandler<MouseEvent> mouseEventEventHandler;
    EventHandler<KeyEvent> keyEventEventHandler;

    boolean move_right, move_left;

    public InputHandler(JfxBreakoutApp app){
        this.app = app;

        keyEventEventHandler = new EventHandler<KeyEvent>() {
            @Override
            public void handle(KeyEvent event) {
                boolean state = false;
                if(event.getEventType() == KeyEvent.KEY_PRESSED) {
                    state = true;
                } else if (event.getEventType() == KeyEvent.KEY_RELEASED) {
                    state = false;
                }
                switch (event.getCode()){
                    case A:
                    case LEFT:
                        move_left = state;
                        break;
                    case D:
                    case RIGHT:
                        move_right = state;
                        break;
                }

            }
        };
        app.gameScene.setOnKeyPressed(keyEventEventHandler);
        app.gameScene.setOnKeyReleased(keyEventEventHandler);
    }
}

Paddle.java


package ceccs;

import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;

public class Paddle extends Rectangle {
    JfxBreakoutApp app;

    double x,y;
    double vx,vy;
    double width, height;
    final double baseSpeed = 1;

    public Paddle(double width, double height, JfxBreakoutApp app){
        this.app = app;
        this.width = width;
        this.height = height;
        x = app.width/2 - width/2;
        y = app.height - 1.5*height;
        vx = 0;
        vy = 0;
        setFill(Color.CYAN);
        updateGraphics();
        app.motionPane.getChildren().add(this);
    }

    public void updateMotion(){
        x += vx;
        y += vy;
    }

    public void updateCollision(){
        //left edge boundary
        if(x < 0) x = 0;
        if(x > app.width - this.width){
            x = (app.width - this.width);
        }

    }

    public void updateGraphics(){
        setLayoutX(x);
        setLayoutY(y);
        setWidth(width);
        setHeight(height);
    }
}

ClassFile.java


package ceccs;

import javafx.animation.AnimationTimer;

public class GameTimer extends AnimationTimer {

...

    @Override
    public void handle(long now) {
        updateInput();  //Added
        updateMotion();
        updateCollision();
        updateGraphics();
    }

    private void updateInput(){
        if(app.inputHandler.move_left && !app.inputHandler.move_right){
            //go left
            app.paddle.vx = -1.0 * app.paddle.baseSpeed;
        } else if(!app.inputHandler.move_left && app.inputHandler.move_right){
            //go right
            app.paddle.vx = app.paddle.baseSpeed;
        } else {
            // x halt
            // you are pressing both or niether...
            app.paddle.vx = 0;
        }

    }


    private void updateMotion(){
        app.ball.updateMotion();
        app.paddle.updateMotion(); //
    }

    private void updateCollision(){
        app.ball.updateCollision();
        app.paddle.updateCollision(); //
    }

    private void updateGraphics(){
        app.ball.updateGraphics();
        app.paddle.updateGraphics(); //
    }
}

ClassFile.java


//file