我正在制作一款游戏,其中包含一个我想用WASD移动的玩家 . 我已经决定使用Key Bindings来尝试修复我使用Key Listeners时出现的问题,即使在切换到Key Bindings后,它仍然会发生 . 问题是,即使按下这些键正在移动播放器,在移动播放器几次后,输入开始几乎完全停止工作 . 这恰好可能只有1/10按键移动玩家 . 我能做错什么?任何帮助将非常感激 .
这是我的游戏的主要类与键绑定:(让我知道我是否应该发布我的其余代码)
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JComponent;
import java.lang.Math;
import java.util.LinkedList;
import java.awt.event.KeyEvent;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.KeyStroke;
public class ZombieMain extends JPanel implements ActionListener{
private static int WIDTH = 1600;
private static int HEIGHT = 900;
private Action a,s,w,d,ra,rs,rw,rd;
private LinkedList<Zombie> zombies = new LinkedList();
Zombie z = new Zombie(100,100,50,30,50);
static ZombiePlayer player = new ZombiePlayer(950,572,2,30);
public ZombieMain(){
this.setFocusable(true);
this.requestFocus();
Timer t = new Timer(10,this);
t.start();
Action w = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
player.vY = -player.speed;
}
};
Action s = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
player.vY = player.speed;
}
};
Action d = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
player.vX = player.speed;
}
};
Action a = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
player.vX = -player.speed;
}
};
Action rw = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
player.vY = 0;
}
};
Action rs = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
player.vY = 0;
}
};
Action rd = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
player.vX = 0;
}
};
Action ra = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
player.vX = 0;
}
};
getInputMap().put(KeyStroke.getKeyStroke("W"),"w");
getInputMap().put(KeyStroke.getKeyStroke("S"),"s");
getInputMap().put(KeyStroke.getKeyStroke("D"),"d");
getInputMap().put(KeyStroke.getKeyStroke("A"),"a");
getInputMap().put(KeyStroke.getKeyStroke("released W"),"rw");
getInputMap().put(KeyStroke.getKeyStroke("released S"),"rs");
getInputMap().put(KeyStroke.getKeyStroke("released D"),"rd");
getInputMap().put(KeyStroke.getKeyStroke("released A"),"ra");
getActionMap().put("w",w);
getActionMap().put("s",s);
getActionMap().put("d",d);
getActionMap().put("a",a);
getActionMap().put("rw",rw);
getActionMap().put("rs",rs);
getActionMap().put("rd",rd);
getActionMap().put("ra",ra);
}
public void actionPerformed(ActionEvent e){
repaint();
}
public void paint(Graphics g){
g.setColor(new Color(40,40,40));
g.fillRect(0,0,WIDTH,HEIGHT);
z.draw((Graphics)g);
player.draw((Graphics)g);
}
public int getWidth(){
return WIDTH;
}
public int getHeight(){
return HEIGHT;
}
public static void main(String[] args){
JFrame frame = new JFrame();
frame.add(new ZombieMain());
frame.setSize(WIDTH,HEIGHT);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.setResizable(false);
}
}
1 回答
关于“为什么”你有问题,我只能猜测,因为我们只有一个脱离上下文的片段来处理,但是,有许多事情可以改进,这可能有助于解决问题 .
调用
getInputMap
时WHEN_IN_FOCUSED_WINDOW
这适用于实际触发键事件的上下文,在上述情况下,当窗口具有焦点时将触发键事件,而不管当前哪个组件具有键盘焦点 .
paintComponent
overpaint
在Swing中绘画是一些复杂的,如一般建议,当你想要执行自定义绘画时,最好覆盖
paintComponent
. 这样做的一个很好的副作用是,它会为你的组件绘制背景颜色,你需要做的一件事;)getPreferredSize
覆盖
getWidth
和getHeight
将导致可能的问题无法结束,最好避免 . 相反,覆盖getPreferredSize
,这样,您将参与布局API并获得其所有优势,例如能够在JFrame
上调用pack
并让它处理围绕框架装饰的所有奇怪事项 .很好的罗嗦“解耦你的代码” . 在您的代码中,玩家的状态由关键操作直接更改 . 这不仅是一个坏主意,它可能产生意想不到的副作用,并且随着需求变得更加复杂而变得越来越难以管理 . 它还使得改变输入的方式变得困难 . 例如,您可以包含不同的输入方法,例如游戏杆,但您必须为其编写相同的代码 .
相反,你应该只有一个“状态管理器”,它带有输入的当前状态,当你的“主循环”准备就绪时,它会将该状态应用于模型,作为一个单独的步骤 .
“主循环”并不关心状态如何更新,只是它可以获得决定如何应用它所需的信息 .
下面是我上面讨论的所有内容的粗略示例,在我的测试中,我没有遇到绑定“拖延”的问题
我应该指出,这只是一种方法 . 也可以把一堆"flags"放在某种
Set
中