0

I'm trying to learn Java and game programming by myself by just playing around with some different things. But now I have come across this problem, when my java app goes fullscreen via GraphicsDevice, the KeyListeners don't work. It's like it doesn't register anything when I press the buttons on my keyboard. When the app isn't fullscreen, everything works as it is supposed to.

I am using Mac.

The code is a bit messy, but it should be somewhat easy to navigate etc.

Game.class

public class Game extends Canvas implements Runnable {
    private static final long serialVersionUID = 1L;

    // Render Vars
    public static final int WIDTH = 1280;
    public static final int HEIGHT = 800; //WIDTH / 16 * 
    public static final int SCALE = 1;
    public final static String TITLE = "Test Game - inDev 1.0.0";
    public static boolean fullscreen = false;

    public static JFrame window = new JFrame(TITLE);

    public static Font defaultFont = new Font("Dialog", Font.PLAIN, 12);
    public static Color defaultColor = Color.gray;

    // Thread Vars
    public static boolean running = false;
    private static Thread thread;
    private BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);

    // Mechanic Vars
    public static boolean mouseDown;
    public static int mouseX;
    public static int mouseY;

    // Game Vars
    public static GameState gameState = new Play();
    public static boolean keyPressed;

    public static Game game = new Game();

    public static void main(String arghs[]) {
        game.setSize(new Dimension(WIDTH, HEIGHT));
        game.setPreferredSize(new Dimension(WIDTH, HEIGHT));

        fullscreen = true;

        window.add(game);
        window.setUndecorated(true);
        window.pack();
        window.setLocationRelativeTo(null);
        window.setResizable(false);
        window.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        window.setVisible(true);

        // HERE I GO FULLSCREEN
        GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().setFullScreenWindow(window);

        game.addKeyListener(new KeyEventListener());
        game.addMouseListener(new MouseEventListener());

        game.start();
    }

    public void run() {

        init();

        long lastTime = System.nanoTime();
        final double numTicks = 100.0;
        double ns = 1000000000 / numTicks;
        double delta = 0;
        int updates = 0;
        int frames  = 0;
        long timer = System.currentTimeMillis();

        while (running) {
            long now = System.nanoTime();
            delta += (now - lastTime) / ns;
            lastTime = now;
            if (delta >= 1) {
                update();
                updates++;
                delta--;
            }
            render();
            frames++;

            if (System.currentTimeMillis() - timer > 1000) {
                timer += 1000;
                System.out.println(updates + " Ticks, FPS: " + frames);
                updates = 0;
                frames = 0;
            }
        }
        stop();
    }

    private synchronized void start() {
        if (running) {
            return;
        }
        running = true;

        thread = new Thread(this);
        thread.setName("My Game");
        thread.start();
    }
    public synchronized static void stop() {
        if (!running) {
            return;
        }
        running = false;

        thread = null;
        System.exit(1);
    }

    private void init() {
        gameState.init();
    }

    private void update() {
        gameState.update();
    }

    private void render() {
        BufferStrategy bs = this.getBufferStrategy();
        if (bs == null) {
            createBufferStrategy(3);
            return;
        }
        Graphics g = bs.getDrawGraphics();

        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);

        g.setColor(defaultColor);
        g.drawImage(image, 0, 0, getWidth(), getHeight(), this);

        // Draw Content
        gameState.render(g);

        // Draw to Screen;
        g.dispose();
        bs.show();
    }

    public static void setGameState(GameState state) {
        gameState = state;
        gameState.init();
    }
}

KeyEventListener.class

public class KeyEventListener extends KeyAdapter {
    public void keyPressed(KeyEvent e) {
        if (!Game.keyPressed) {
            Game.gameState.keyPressed(e);
        }
        Game.keyPressed = true;
    }
    public void keyReleased(KeyEvent e) {
        Game.gameState.keyReleased(e);
        Game.keyPressed = false;
    }
}

MouseEventListener.class (Just for recording the mouse position)

public class MouseEventListener extends MouseAdapter {

    public void mousePressed(MouseEvent e) {
        Game.mouseDown = true;
    }
    public void mouseReleased(MouseEvent e) {
        Game.mouseDown = false;
    }
    public void mouseMoved(MouseEvent e) {
        Game.mouseX = e.getX();
        Game.mouseY = e.getY();
    }
    public void mouseDragged(MouseEvent e) {
        Game.mouseX = e.getX();
        Game.mouseY = e.getY();
    }
}

GameState.class

public abstract class GameState {

    public abstract void init();
    public abstract void update();
    public abstract void render(Graphics g);
    public void keyPressed(KeyEvent e) {

    }
    public void keyReleased(KeyEvent e) {

    }

}

And my Play.class which is the current gameState

public class Play extends GameState {

    public static int key;

    public void init() {

    }

    public void update() {

    }   

    public void render(Graphics g) {
        g.drawString("Key: " + key, 100, 100);
    }

    public void keyPressed(KeyEvent e) {
        key = e.getKeyCode();
    }

    public void keyReleased(KeyEvent e) {

    }

}
Phoenix1355
  • 1,589
  • 11
  • 16
  • 3
    Where's the `KeyEventListener` and the `MouseEventListener`? Where's `GameState`? – MadProgrammer Jun 11 '14 at 08:16
  • The `KeyEventListener`, `MouseEventListener`and the `GameState` is all three some seperate classes which I made. They all work fine except the `KeyEventListener` when my app is fullscreen which is my problem. – Phoenix1355 Jun 11 '14 at 08:19
  • Yep, but it means we can't run the program, or when we adjust for these missing classes, we might not get the same results as you do... – MadProgrammer Jun 11 '14 at 08:21
  • 1) For better help sooner, post an [MCVE](http://stackoverflow.com/help/mcve) (Minimal Complete and Verifiable Example). 2) For Swing, typically use key bindings over the AWT based, lower level, `KeyListener`. See [How to Use Key Bindings](http://docs.oracle.com/javase/tutorial/uiswing/misc/keybinding.html) for details on how to use them. – Andrew Thompson Jun 11 '14 at 08:33
  • Just added the code for the 4 other classes in my project. Now you should be able to create the same result, if you have a Mac of course. – Phoenix1355 Jun 11 '14 at 08:39

1 Answers1

2

KeyListener will only respond to key events when the component is registered to is focusable and has focus.

After you have set the window to full screen, try adding...

game.requestFocusInWindow();

You may also need to use game.setFocusable(true)

If it wasn't for the fact that you're using a Canvas, I'd suggest using the key bindings API to over all these focus issues

Updated

I added...

window.addWindowFocusListener(new WindowAdapter() {

    @Override
    public void windowGainedFocus(WindowEvent e) {
        System.out.println("gainedFocus");
        if (!game.requestFocusInWindow()) {
            System.out.println("Could not request focus");
        }
    }

});

To the window after it was visible but before it was made full screen

Updated

Oh, you're going to love this...

Based on this question: FullScreen Swing Components Fail to Receive Keyboard Input on Java 7 on Mac OS X Mountain Lion

I added setVisible(false) followed by setVisible(true) after setting the window to full screen mode and it seems to have fixed it...

GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().setFullScreenWindow(window);
window.setVisible(false);
window.setVisible(true);

Verified running on Mac, using Java 7

Community
  • 1
  • 1
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • Hmm... It doesn't seem to work. It still doesn't register any key events. As said I'm just learning to program java. I don't have a lot of experience so far. And I'm using `Canvas` since a tutorial I followed once used it. The application do work on `Windows OS` though. So I think it might be something with the fact that I'm using a Mac. – Phoenix1355 Jun 11 '14 at 08:27
  • 1
    It's most likely a timing issue, you need to catch the window at just the right moment... – MadProgrammer Jun 11 '14 at 08:29