Question

People here keep suggesting to me to use Key Bindings in my Java 2D games instead of Key Listener.

So I learned it and I'd like to know wether I understand correctly how to use it.

Let's say I have a game, with two playes, each player can push 5 buttons.

Player 1:

  • UP arrow - move forward
  • LEFT arrow - change angle of movement
  • RIGHT arrow - change angle of movement
  • SPACE key - fire missile
  • L key - fire secondary missile

Player 2:

  • W key - move forward
  • A key - change angle of movement
  • D key - change angle of movement
  • CAPS-LOCK key - fire missile
  • 'Z' key - fire secondary missile

If I want the program to react differently to each one of the different key-presses, than this is what I have to do: (?)

  1. Create 10 new nested classes extending AbstractAction, inside the class that runs most of the game logic.
  2. Create an instance of every one of these 10 new classes, and bind each one to a key.

Is this correct? Is it really logical to create 10 new classes only for pushing buttons? I want to know if I understand correctly how to use Key Bindings, so I can start programming with it.

Thanks

Was it helpful?

Solution

"Is this correct? Is it really logical to create 10 new classes only for pushing buttons?"

The answer is YES. You do need to create 10 different instances. It's not difficult. You can either create a helper class or you can just copy and paste something like this

Action leftAction = new AbstractAction(){
    public void actionPerformed(ActionEvent e){
        // do something when left button pressed;
    }
};

InputMap inputMap = panel.getInputMap(JPanel.WHEN_IN_FOCUSED_WINDOW);
ActionMap actionMap = panel.getActionMap();

inputMap.put(KeyStroke.getKeyStroke("LEFT"), "leftAction");
actionMap.put("leftAction", leftAction);  <----

For each different action, just copy and paste the Action code, change the variable, and the action to perform, and input into the InputMap and the ActionMap accordingly.

I use both ways for different scenarios. For graphics i prefer the above way. For things like menus, I tend to use a separate class

Take a look at this example

OTHER TIPS

public TestKeyBindings02() {
    JPanel panel = new JPanel();
    InputMap im = panel.getInputMap(JPanel.WHEN_IN_FOCUSED_WINDOW);
    ActionMap am = panel.getActionMap();

    im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), "RightArrow");
    im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), "LeftArrow");
    im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), "UpArrow");
    im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), "DownArrow");

    am.put("RightArrow", new ArrowAction("RightArrow"));
    am.put("LeftArrow", new ArrowAction("LeftArrow"));
    am.put("UpArrow", new ArrowAction("UpArrow"));
    am.put("DownArrow", new ArrowAction("DownArrow"));
}

public class ArrowAction extends AbstractAction {

    private String cmd;

    public ArrowAction(String cmd) {
        this.cmd = cmd;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (cmd.equalsIgnoreCase("LeftArrow")) {
            System.out.println("The left arrow was pressed!");
        } else if (cmd.equalsIgnoreCase("RightArrow")) {
            System.out.println("The right arrow was pressed!");
        } else if (cmd.equalsIgnoreCase("UpArrow")) {
            System.out.println("The up arrow was pressed!");
        } else if (cmd.equalsIgnoreCase("DownArrow")) {
            System.out.println("The down arrow was pressed!");
        }
    }
}

Taken from here

Personaly, when I was using keyBindings I would create an inner class extending abstractAction for each action, then create an instance of this inner class and bind it to a key like put("left", ActionLeft);, for example. So basically I did the two steps you've described and that worked.

You could also just create instances of anonymus classes and then bind those instances just the same way.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top