我正在尝试制作一个平台,但我坚持如何一次检测多个按键。例如,如果我使用运行键并向前运行,然后我点击跳转键,游戏仍然需要知道是否正在按下运行键
答案 0 :(得分:2)
这比我正常做的更复杂。通常我会允许每个Action
直接改变游戏状态。
此示例显示如何使用key bindings API监控某些键的按下/释放,并在中央池中添加/删除它们。
使用此API的主要原因是它在焦点上下文时克服了KeyListener
的限制。只要窗口具有焦点,此示例将检索按键通知。
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();
}
}
}
答案 1 :(得分:1)
尝试使用HashSet
的自定义类来跟踪按下的键...
class MultiKeyPressListener implements KeyListener {
// Set of currently pressed keys
private final Set<Character> pressed = new HashSet<Character>();
@Override
public synchronized void keyPressed(KeyEvent e) {
pressed.add(e.getKeyChar());
if (pressed.size() > 1) {
// More than one key is currently pressed.
// Iterate over pressed to get the keys.
}
}
@Override
public synchronized void keyReleased(KeyEvent e) {
pressed.remove(e.getKeyChar());
}
@Override
public void keyTyped(KeyEvent e) {/* Not used */ }
}