簡體   English   中英

無法獲取Java密鑰版本?

[英]Java key releases not being picked up?

我是Java編程的新手,已經開始編寫游戲。 我有一個隨wasd移動的角色,但發現在以下情況下:

  1. 按下移動鍵。
  2. JFrame單擊離開。 (因此變得沒有重點。)
  3. 釋放相同的密鑰。
  4. JFrame再次聚焦。

...游戲不會發現玩家不應該移動。 因此,我嘗試通過將所有keys數組更改為false來解決此問題:

public class KeyManager implements KeyListener {

private Game game;

private boolean[] keys;
public boolean up, down, left, right; //Player class reads these variables

public KeyManager(Game game) {
    this.game = game;
    keys = new boolean[256];
}

public void tick() {
    if(!game.getDisplay().getFrame().isFocused()) { //Here is the problem
        for(int i = 0; i < keys.length; i++) {
            keys[i] = false; //Repeats 256 x 60 times a second
        }
    }
    up = keys[KeyEvent.VK_W];    //I realize that I could just change
    down = keys[KeyEvent.VK_S];  //up, down, left, right to false but
    left = keys[KeyEvent.VK_A];  //when the JFrame is refocused the game
    right = keys[KeyEvent.VK_D]; //still doesn't know the key was released
}

@Override
public void keyPressed(KeyEvent e) {
    keys[e.getKeyCode()] = true;
}

@Override
public void keyReleased(KeyEvent e) {
    keys[e.getKeyCode()] = false;
}

@Override
public void keyTyped(KeyEvent e) {

}

}

它起作用了,但是在考慮了代碼之后,我意識到由於tick()方法每秒被調用60次,並且keys數組的長度為256個鍵,因此它僅需要4個重要鍵就每秒更新一次15,900個布爾布爾值。更改為false。

最有效的方法是什么? 我覺得我缺少一些非常簡單的東西。

我要做的第一件事是使用Key Bindings API而不是KeyListener 我希望它獨立於“游戲循環”來更新鍵標志(個人而言,我將使用Set和某種類型的Input enum ,但就是我)。

然后,我將在JFrame上使用FocusListener並在失去/獲得焦點時簡單地暫停/恢復“游戲循環”,可以選擇重置鍵標志

像這樣的東西...

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

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

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

                JFrame frame = new JFrame("Testing");
                TestPane tp = new TestPane();
                frame.addFocusListener(new FocusListener() {
                    @Override
                    public void focusGained(FocusEvent e) {
                        tp.resume();
                    }

                    @Override
                    public void focusLost(FocusEvent e) {
                        tp.pause(true);
                    }
                });
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(tp);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private boolean aPressed = false;
        private Timer timer;

        public TestPane() {
            InputMap inputMap = getInputMap(WHEN_IN_FOCUSED_WINDOW);
            ActionMap actionMap = getActionMap();

            inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_A, 0, false), "A.pressed");
            inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_A, 0, true), "A.released");
            actionMap.put("A.pressed", new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    aPressed = true;
                }
            });
            actionMap.put("A.released", new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    aPressed = false;
                }
            });

            timer = new Timer(16, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    System.out.println("A pressed = " + aPressed);
                }
            });
        }

        public void resume() {
            timer.restart();
        }

        public void pause(boolean reset) {
            timer.stop();
            if (reset) {
                aPressed = false;
            }
        }

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

    }

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM