gpt4 book ai didi

java - 如何在java中创建可用的KeyReleased方法

转载 作者:行者123 更新时间:2023-11-30 06:03:10 26 4
gpt4 key购买 nike

我是 Swing 新手,我正在尝试让方 block 移动,但只有当释放按键时(例如 W),但当我按住按键时,方 block 才会移动

KeyListener类

我想确保按下了一个键,如果仍然按下它应该返回 false,但如果按下然后释放它应该返回 true 包 javaGD.GameAssistant.Input;

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

public class KeyManager implements KeyListener {
private boolean[] keys;

public KeyManager() {
keys = new boolean[256];

}

@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) {

}

public boolean KeyPressed(int keycode) {
return keys[keycode];

}

public boolean KeyReleased(int keycode) {
return keys[keycode];
}
}

方 block 应该移动的类。KeyListener继承自GameAssistant(JFrame是用KeyListener创建的)

package TestCode;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.KeyEvent;

import javaGD.GameAssistant.GameAssistant;

public class Game extends GameAssistant {
public int x, xSpeed, y, ySpeed;

public Game(String title, int width, int height, boolean makeResizable) {
super(title, width, height, makeResizable);

}

@Override
public void setup() {
x = 0;
y = 0;
xSpeed = 5;
ySpeed = 5;
}

@Override
public void update() {
if (this.Keyboard().KeyReleased(KeyEvent.VK_D)) {
x += xSpeed;
}

if (this.Keyboard().KeyReleased(KeyEvent.VK_A)) {
x -= xSpeed;
}

if (this.Keyboard().KeyReleased(KeyEvent.VK_W)) {
y -= ySpeed;
}

if (this.Keyboard().KeyReleased(KeyEvent.VK_S)) {
y += ySpeed;
}
}

@Override
public void draw(Graphics g) {

g.setColor(Color.BLACK);
g.fillRect(x, y, 20, 20);

}

}

最佳答案

KeyReleased 应该返回 !keys[keycode],否则释放时返回 false,按下时返回 true

public boolean KeyReleased(int keycode) {
return !keys[keycode];
}

我还建议使用 Key bindings API 而不是 KeyListener,因为它更可靠且可重用。

如果您只计划有限数量的输入操作,我会使用 Setenum ,这样您就可以将“如何”与“什么”解耦。

update 方法不关心“如何”管理输入,只关心“状态是什么”

从概念上讲,也许像......

public enum GameInput {
UP, DOWN, LEFT, RIGHT;
}

public class KeyManager implements KeyListener {

private Set<GameInput> inputs = new HashSet<>();

public KeyManager() {
}

@Override
public void keyPressed(KeyEvent e) {
// Check the key code, verify if it's one of the configured
// actions keys
// The key code could come from a configuration file which might
// be customisable by the user...
if (e.getKeyCode() == KeyEvent.VK_W) {
inputs.add(GameInput.UP);
} else if (e.getKeyCode() == KeyEvent.VK_S) {
// etc...
} // etc...
}

@Override
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_W) {
inputs.remove(GameInput.UP);
} else if (e.getKeyCode() == KeyEvent.VK_S) {
// etc...
} // etc...
}

@Override
public void keyTyped(KeyEvent e) {

}

public boolean isKeyPressed(GameInput input) {
return inputs.contains(input);

}

public boolean isKeyReleased(GameInput input) {
return !isKeyPressed(input);
}
}

你的 update 方法可能看起来像......

@Override
public void update() {
if (this.Keyboard().isKeyReleased(GameInput.RIGHT)) {
x += xSpeed;
}

if (this.Keyboard().isKeyReleased(GameInput.LEFT)) {
x -= xSpeed;
}

if (this.Keyboard().isKeyReleased(GameInput.UP)) {
y -= ySpeed;
}

if (this.Keyboard().isKeyReleased(GameInput.DOWN)) {
y += ySpeed;
}
}

现在,您的 update 方法不关心输入“如何”生成,只关心设置(或未设置)时要执行的操作。

就我个人而言,我会使用 InputManager 类并进一步解耦它,因此可以通过其他方式生成输入,例如按钮、鼠标输入、游戏 handle 等...

可运行示例...

从概念上讲,这应该可行。我说“概念上”,是因为在测试时我遇到了一些“奇怪”的问题,这些问题我无法为 Java (1.8) 或 MacOS 做出贡献 - 或者因为它们是两者的组合......下面有更多详细信息...

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.util.HashSet;
import java.util.Set;
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;

public class Test {

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

public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}

public class TestPane extends JPanel {

private Box box = new Box();

public TestPane() {
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap am = getActionMap();

im.put(KeyStroke.getKeyStroke(KeyEvent.VK_W, 0, false), "Up.pressed");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_W, 0, true), "Up.released");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_S, 0, false), "Down.pressed");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_S, 0, true), "Down.released");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_A, 0, false), "Left.pressed");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_A, 0, true), "Left.released");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_D, 0, false), "Right.pressed");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_D, 0, true), "Right.released");

am.put("Up.pressed", new KeyAction(InputAction.UP, true));
am.put("Up.released", new KeyAction(InputAction.UP, false));
am.put("Down.pressed", new KeyAction(InputAction.DOWN, true));
am.put("Down.released", new KeyAction(InputAction.DOWN, false));
am.put("Left.pressed", new KeyAction(InputAction.LEFT, true));
am.put("Left.released", new KeyAction(InputAction.LEFT, false));
am.put("Right.pressed", new KeyAction(InputAction.RIGHT, true));
am.put("Right.released", new KeyAction(InputAction.RIGHT, false));

Timer timer = new Timer(5, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
box.update(getBounds());
repaint();
}
});
timer.start();
}

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

@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
box.draw(g);
}

}

public class Box {

public int x, xSpeed, y, ySpeed, width, height;

public Box() {
x = 0;
y = 0;
xSpeed = 1;
ySpeed = 1;
width = 10;
height = 10;
}

public void update(Rectangle bounds) {
if (!InputManager.INSTANCE.isSet(InputAction.LEFT)) {
x -= xSpeed;
}
if (!InputManager.INSTANCE.isSet(InputAction.RIGHT)) {
x += xSpeed;
}
if (InputManager.INSTANCE.isSet(InputAction.UP) && InputManager.INSTANCE.isSet(InputAction.DOWN)) {
//
} else if (!InputManager.INSTANCE.isSet(InputAction.UP)) {
y -= ySpeed;
} else if (!InputManager.INSTANCE.isSet(InputAction.DOWN)) {
y += ySpeed;
}

if (x < bounds.x) {
x = 0;
} else if (x + width > (bounds.x + bounds.width)) {
x = bounds.x + (bounds.width - width);
}
if (y < bounds.y) {
y = 0;
} else if (y + height > (bounds.y + bounds.height)) {
y = bounds.y + (bounds.height - height);
}
}

public void draw(Graphics g) {
g.setColor(Color.BLACK);
g.fillRect(x, y, width, height);
}
}

public enum InputAction {
UP, DOWN, LEFT, RIGHT;
}

public enum InputManager {
INSTANCE;

private Set<InputAction> actions = new HashSet<>();

public void set(InputAction action) {
actions.add(action);
}

public void remove(InputAction action) {
actions.remove(action);
}

public boolean isSet(InputAction action) {
return actions.contains(action);
}
}

public class KeyAction extends AbstractAction {

private InputAction action;
private boolean apply;

public KeyAction(InputAction action, boolean apply) {
this.action = action;
this.apply = apply;
}

@Override
public void actionPerformed(ActionEvent e) {
System.out.println("!");
if (apply) {
System.out.println("Apply " + action);
InputManager.INSTANCE.set(action);
} else {
System.out.println("Remove " + action);
InputManager.INSTANCE.remove(action);
}
}
}
}

TL;DR

在测试上面的示例时,我遇到了一些奇怪的问题,这是我以前从未见过的(并不是说我最近一直在做这种事情)。

当使用 KeyListener 时,如果我按下(并按住)两个按钮,我可以看到“按下” Action ,但没有重复事件,这是我通常期望的(对于任何键)。当我松开按键时,我看到了“释放” Action ,但是当我按下(并按住)时,没有生成新的“按下” Action 。

我尝试了按键绑定(bind) API(如上所示),但仍然没有成功(类似的结果)。

然后,我将 AWTEventListener 直接附加到事件队列并监视所有击键。

我注意到,有时(即使只是重复敲击一个键)可能不会生成“按下”。

我还注意到,按住一个或多个键,释放并再次按下一个键,通常不会生成新的按下事件(仅释放事件)

我使用的是 macOS 10.13.6 和 Java 1.8.0_144-b01 - 这可能是其中一个或两个中的错误,但我没有其他方法来测试它

更新...

因此,从 Java 1.8 更新到 Java 1.10 后,上述问题似乎得到了解决 - 然而,这突出了另一个硬件问题,即一次只能主动按下一定数量的按键 - 请参阅 How do I remove the limit on PC keyboard button presses?更多详情

关于java - 如何在java中创建可用的KeyReleased方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51866760/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com