API связывания ключей (и действия) пытается отделить понятие «ввод» от «действия».Это позволяет вам иметь несколько типов «входов», которые могут запускать одно и то же действие.
Например, у вас могут быть кнопки, нажатия клавиш, джойстик или другой внешний контроллер, способный генерировать "стрелять "вход.Вместо этого нужно написать код для каждого из этих входов, который «в конечном итоге» запускает какое-то действие.Вы можете просто связать их все с одним «действием» в лаконичной манере, которая отделена друг от друга (способ, которым вы могли бы связать ввод джойстика, был бы другим, чем для кнопок или нажатий клавиш).
Такпервое, что нам нужно, так или иначе, это указать, что «спусковой крючок» был нажат (или отпущен), может быть, что-то вроде ...
public class ShootAction extends AbstractAction {
private boolean isShooting;
public ShootAction(boolean isShooting) {
this.isShooting = isShooting;
}
@Override
public void actionPerformed(ActionEvent e) {
}
}
Хорошо, это скучно и нена самом деле "делать" что-нибудь.Нам нужен какой-то «менеджер состояний», который может сказать, что триггер был нажат или отпущен.Важно отметить, что ShootAction
не несет ответственности за решение «что» или «как» происходит, она должна быть сосредоточена исключительно на уведомлении «модели» или «контроллера» о том, что состояние изменилось, чтобы оно могло реагировать наэто каким-то осмысленным образом.
Итак, предположим, что у нас есть некоторый контроллер, который обеспечивает управление состоянием съемки ...
public class SomeAwesomeGameController ... {
public void setShooting(boolean shooting) {...}
public boolean isShooting() {...}
}
Мы можем передать его экземпляр в действие и использовать егообновить состояние ...
public class ShootAction extends AbstractAction {
private boolean isShooting;
private SomeAwesomeGameController controller;
public ShootAction(SomeAwesomeGameController controller, boolean isShooting) {
this.controller = controller;
this.isShooting = isShooting;
}
@Override
public void actionPerformed(ActionEvent e) {
controller.setShooting(isShooting);
}
}
Одна из причин сделать это таким образом (кроме разъединения кода) состоит в том, что существует задержка ОС между первым нажатием клавиши и повторными нажатиями клавиши.Устраняя необходимость полагаться на фактические повторяющиеся события (заботясь только об изменении состояния), мы удаляем эту задержку.
И, наконец, мы можем связать все это вместе: P
public class PlayerTwo ... {
// Don't forget to assign this value ;)
private SomeAwesomeGameController controller;
public PlayerTwo() {
InputMap im = getInputMap(JPanel.WHEN_IN_FOCUSED_WINDOW);
ActionMap am = getActionMap();
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0, false), "space.pressed");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0, true), "space.released");
am.put("space.pressed", new ShootAction(controller, true));
am.put("space.released", new ShootAction(controller, false));