0

So for reference, I am following Trystan's roguelike tutorial for java.

The tutorial above uses Key Listeners, which does not work for Mac OS X (and appears to be discouraged by the community), so I am trying to change the code to use Key Bindings instead.

Here's the question. In his "roguelike game", the game is divided into screens, where each screen has separate actions for a particular key. For instance, the "Start Screen" sends the player to the "Play screen" upon pressing the enter key:

public class StartScreen implements Screen {

    public void displayOutput(AsciiPanel terminal) {
        terminal.write("rl tutorial", 1, 1);
        terminal.writeCenter("-- press [enter] to start --", 22);
    }

    public Screen respondToUserInput(KeyEvent key) {
        return key.getKeyCode() == KeyEvent.VK_ENTER ? new PlayScreen() : this;
    }
}

While the "Play Screen" sends the player to the "Win screen" upon pressing the enter key:

public class PlayScreen implements Screen {

    public void displayOutput(AsciiPanel terminal) {
        terminal.write("You are having fun.", 1, 1);
        terminal.writeCenter("-- press [escape] to lose or [enter] to win --", 22);
    }

    public Screen respondToUserInput(KeyEvent key) {
        switch (key.getKeyCode()){
        case KeyEvent.VK_ESCAPE: return new LoseScreen();
        case KeyEvent.VK_ENTER: return new WinScreen();
        }

        return this;
    }
}

Now, from what I can see from Key Bindings examples such as this and this, all the bindings and actions seem to be "dumped" into one class. This is unsatisfactory, because:

  1. One keystroke leads to only one action (I suppose I could have the action do a switch case, and check what screen I am in, and then execute some code specific to said screen, but perhaps there is a better way.)
  2. It becomes more difficult to determine what action is from/for what screen.

Would there be a way to get Key Bindings to have one keystroke execute different actions depending on the "Screen"? Would I just use conditionals? Can I put Key Binding logic in other classes (Screens) and then call them in the main class, like what is happening with Key Listeners above?

Community
  • 1
  • 1
therladbsgh
  • 71
  • 1
  • 4
  • Couldn't you just register different bindings to each screen? Every component has it's own inputmap and actionmap – Vince Apr 09 '15 at 17:06
  • The program itself appears to have only one JFrame component (with the JFrame drawing different screens based on different conditions.) – therladbsgh Apr 09 '15 at 17:15

1 Answers1

2

Key bindings are not necessarily dumped into one class. They are associated with input maps, which in turn are associated with specific JComponents. If you register screen-specific bindings in the WHEN_ANCESTOR_OF_FOCUSED_COMPONENT input map of the JComponent representing that screen, then they will be recognized when any component in that screen has the keyboard focus (supposing a component in between has not overridden the binding with its own), but not when a component in a different screen has the focus.

Overall, the system is very flexible. You might consider reading the Java Tutorial section on this topic to bring yourself up to speed.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
  • Thanks for the reply. I think the problem is how the game is setup; it has one JFrame and one AsciiPanel (JPanel) which simply changes display to show different screens. The "screens" are not JComponents so I can't directly put Key Bindings there, but perhaps I can just put a method that puts Key Bindings to the AsciiPanel itself. I'll see if that works. – therladbsgh Apr 09 '15 at 17:40
  • 1
    You can change the registered key bindings when a different "screen" is displayed. And if there really is no separate `JComponent` that can be associated with each logical screen overall, then perhaps it would make sense to create one. – John Bollinger Apr 09 '15 at 17:49