在java中检测多个按键 [英] Detecting multiple keypresses in java

查看:112
本文介绍了在java中检测多个按键的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在努力建立一个平台,但我坚持如何一次检测多个按键。例如,如果我使用运行键并向前运行,然后我点击跳转键,游戏仍然必须知道是否正在按下运行键

I'm trying to make a platform, but im stuck on how to detect multiple key presses at once. For example, if I was using the run key and running forward, and then I hit the jump key the game still has to know if the run key is being pressed

推荐答案

这比我常做的更复杂。通常我会允许每个 Action 直接更改游戏状态。

This is a little more convoluted then I would normal do. Normally I would allow each Action to directly change the game state.

此示例显示如何使用键绑定用于监控某些键的按下/释放并添加/删除的API他们来自中央游泳池。

This example shows how to use the key bindings API to monitor press/release of certain keys and add/remove them from a central pool.

使用此API的主要原因是它在焦点上下文时克服了 KeyListener 的限制。只要窗口具有焦点,此示例将检索按键通知。

The main reason for using this API is that it overcomes the limitations of the KeyListener when it comes to focus context. This example will retrieve notifications of key presses so long as the window has focus.

public class TestMultyKeyPress {

    public static void main(String[] args) {
        new TestMultyKeyPress();
    }

    public TestMultyKeyPress() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException ex) {
                } catch (InstantiationException ex) {
                } catch (IllegalAccessException ex) {
                } catch (UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Test");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new KeyPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }

        });
    }

    public class KeyPane extends JPanel implements KeyManager {

        private TrianglePane upPane;
        private TrianglePane downPane;
        private TrianglePane leftPane;
        private TrianglePane rightPane;
        private List<Integer> keysList = new ArrayList<>(25);

        public KeyPane() {
            setLayout(new GridBagLayout());
            upPane = new TrianglePane(0);
            leftPane = new TrianglePane(1);
            downPane = new TrianglePane(2);
            rightPane = new TrianglePane(3);
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridx = 1;
            gbc.gridy = 0;
            add(upPane, gbc);

            gbc.gridx = 0;
            gbc.gridy++;
            add(leftPane, gbc);
            gbc.gridx += 2;
            add(rightPane, gbc);

            gbc.gridx = 1;
            gbc.gridy++;
            add(downPane, gbc);

            InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
            ActionMap am = getActionMap();

            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, false), "KeyPressed.Left");
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, false), "KeyPressed.Right");
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, false), "KeyPressed.Up");
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, false), "KeyPressed.Down");

            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, true), "KeyReleased.Left");
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, true), "KeyReleased.Right");
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, true), "KeyReleased.Up");
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, true), "KeyReleased.Down");

            am.put("KeyPressed.Left", new KeyAction(KeyEvent.VK_LEFT, false, this));
            am.put("KeyPressed.Right", new KeyAction(KeyEvent.VK_RIGHT, false, this));
            am.put("KeyPressed.Up", new KeyAction(KeyEvent.VK_UP, false, this));
            am.put("KeyPressed.Down", new KeyAction(KeyEvent.VK_DOWN, false, this));

            am.put("KeyReleased.Left", new KeyAction(KeyEvent.VK_LEFT, true, this));
            am.put("KeyReleased.Right", new KeyAction(KeyEvent.VK_RIGHT, true, this));
            am.put("KeyReleased.Up", new KeyAction(KeyEvent.VK_UP, true, this));
            am.put("KeyReleased.Down", new KeyAction(KeyEvent.VK_DOWN, true, this));

        }

        @Override
        public void keyPressed(int keyCode) {
            if (!keysList.contains(keyCode)) {
                keysList.add(new Integer(keyCode));
                updateKeyState();
            }
        }

        @Override
        public void keyReleased(int keyCode) {
            keysList.remove(new Integer(keyCode));
            updateKeyState();
        }

        public void updateKeyState() {
            upPane.setActive(keysList.contains(KeyEvent.VK_UP));
            downPane.setActive(keysList.contains(KeyEvent.VK_DOWN));
            leftPane.setActive(keysList.contains(KeyEvent.VK_LEFT));
            rightPane.setActive(keysList.contains(KeyEvent.VK_RIGHT));
        }

    }

    public interface KeyManager {

        public void keyPressed(int keyCode);

        public void keyReleased(int keyCode);

    }

    public class KeyAction extends AbstractAction {

        private int keyCode;
        private boolean released;
        private KeyManager manager;

        public KeyAction(int keyCode, boolean released, KeyManager manager) {
            this.keyCode = keyCode;
            this.released = released;
            this.manager = manager;
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            if (released) {
                manager.keyReleased(keyCode);
            } else {
                manager.keyPressed(keyCode);
            }
        }

    }

    public class TrianglePane extends JPanel {

        private boolean active;
        private TriangleShape shape;

        public TrianglePane(int direction) {

            shape = new TriangleShape(20);
            AffineTransform at = null;
            switch (direction) {
                case 0:
                    at = AffineTransform.getRotateInstance(Math.toRadians(-90), 10, 10); // UP
                    break;
                case 1:
                    at = AffineTransform.getRotateInstance(Math.toRadians(180), 10, 10); // UP
                    break;
                case 2:
                    at = AffineTransform.getRotateInstance(Math.toRadians(90), 10, 10); // UP
                    break;
                case 3:
                    at = AffineTransform.getRotateInstance(Math.toRadians(0)); // UP
                    break;
            }
            shape.transform(at);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(20, 20);
        }

        public void setActive(boolean value) {
            if (active != value) {
                this.active = value;
                repaint();
            }
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            int x = (getWidth() - shape.getBounds().width) / 2;
            int y = (getHeight() - shape.getBounds().height) / 2;
            if (active) {
                g2d.setColor(Color.BLACK);
            } else {
                g2d.setColor(Color.GRAY);
            }
            g2d.fill(shape);
        }

    }

    public class TriangleShape extends Path2D.Float {

        public TriangleShape(int size) {
            moveTo(1, 1);
            lineTo(size - 1, (size - 1) / 2);
            lineTo(1, size - 1);
            closePath();
        }

    }

}

这篇关于在java中检测多个按键的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆