使用KeyBindings调用方法

时间:2018-06-04 04:50:49

标签: java swing graphics jframe key-bindings

我正在创建一个2D游戏,玩家可以在那里射击子弹。我试图找出当玩家按下按键时如何调用拍摄方法。我正在使用Key Bindings,这对我来说是新的。我已阅读API但仍无法使其正常工作。建议会有所帮助

这是我的键盘输入代码:

public PlayerTwo (){
    playertwo = Toolkit.getDefaultToolkit().createImage("cal.png");
    bullets = new ArrayList();
    tm.start();
    InputMap im = getInputMap(JPanel.WHEN_IN_FOCUSED_WINDOW);
    ActionMap am = getActionMap();

    im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, false), "up.pressed");
    im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, true), "up.released");
    im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, false), "down.pressed");
    im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, true), "down.released");
    im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, false), "left.pressed");
    im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, true), "left.released");
    im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, false), "right.pressed");
    im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, true), "right.released");
    im.put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0, false), "space.pressed");
    im.put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0, true), "space.released");


    am.put("up.pressed", new MoveAction(-1, 0));
    am.put("up.released", new MoveAction(0, 0));
    am.put("down.pressed", new MoveAction(1, 0));
    am.put("down.released", new MoveAction(0, 0));
    am.put("left.pressed", new MoveAction(0, -1));
    am.put("left.released", new MoveAction(0, 0));
    am.put("right.pressed", new MoveAction(0, 1));
    am.put("right.released", new MoveAction(0, 0));
    //Shoot.getActionMap();

}

1 个答案:

答案 0 :(得分:0)

Key bindings(和Action)API尝试将“input”的概念与“action”分离。这允许您有多种类型的“输入”,这些“输入”都可以触发相同的操作。

例如,您可能有按钮,键盘敲击,操纵杆或其他外部控制器,所有这些都能够生成“拍摄”输入。而不是必须为每个输入编写“最终”触发某些操作的代码。你可以简单地将它们全部绑定到一个单独的“动作”,它以简洁的方式相互分离(你可以绑定操纵杆输入的方式与按钮或击键相同)。

所以,我们需要的第一件事就是表明“触发器”已被拉动(或释放),可能就像......

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));