我希望在画布或其他组件上移动对象,但这样做没有明显的延迟/延迟。现在,为了解决这个问题,我正在使用具有多个图层的双缓冲(大多数图层只能绘制一次)。在我的情况下,我有一个背景,在地图生成时绘制一次,一个遮罩层(对象后面的东西)和一个边缘层(对象前面的东西)。实际上重新绘制的唯一内容是在屏幕上移动的实际对象。
话虽如此,我还设置了KeyListeners,并将我的对象移动移动到绘图中并处理成单独的线程(例如专用于绘制画布的线程,以及专用于处理移动的线程)。
我注意到当我按下一个键来移动物体(W,A,S,D)时,它会移动一小部分(一个移动动作),然后稍微延迟,然后不断移动直到我停止按键。
是否有更好的方法从键盘实现移动以减少/消除延迟?
CNC中 我意识到我可以在一个声明中总结一下:如何为感觉敏感的游戏制作控件,而不会出现笨拙的延迟/延迟。
答案 0 :(得分:1)
您使用的是哪种操作系统?在linux /可能的mac上,按住一个键会执行几个周期,包括不断调用按下和释放方法(你知道如果你在一个文本框中按住一个键,一个字符出现,然后有一个延迟,然后还有几个看起来很快?在linux中,操作系统执行按下,然后释放,真的非常快。)然而,在Windows中,直到密钥实际发布才会调用发布方法。 (基本上,它只是继续快速调用印刷方法。)
一个非常丑陋和讨厌的答案,但我希望它有所帮助:
知道这些周期的时间是有帮助的。通常情况下,它是这样的:
考虑到这个循环,理论上可以(实际上,完全可能。我已经测试过它。)使用时间来检测用户是否实际释放了密钥。基本上,如果密钥被释放的时间超过10毫秒(我会去15,为了安全起见),那么你知道用户已经释放了密钥。
此解决方案涉及为每个相关键创建一个布尔值。反过来,你的KeyListeners只会将这些布尔值设置为true / false(可能在按下它们时,它们被设置为true,当它们被释放时,它们被设置为false。)
然后,为每个键创建一个布尔值,表示键是否真正被按下。创建一个监视第一个布尔值(由KeyListeners控制的布尔值)的线程。每次将第一个布尔值设置为true时,将相应的第二个布尔值设置为true。
但是,每当第一个布尔值设置为false时,请等待15毫秒,然后再次检查。如果它们仍设置为false,则将相应的第二个布尔值设置为false。为什么?如果它是15毫秒并且它们仍然是假的,那么您知道用户实际已释放该密钥。
KeyListener:
@Override
public void keyPressed(KeyEvent e){
if(e.getKeyCode == 65){
aPressed = true;
}
}
@Override
public void keyReleased(KeyEvent e){
if(e.getKeyCode == 65){
aPressed = false;
}
}
单独的线程(称之为trueKeyListener
)
boolean waiting = false;
long tWaitStart;
Runnable trueKeyListener = new Runnable(){
@Override
public void run(){
while(true){//Instead of true, use some variable, like running
if(aPressed){
aTruePressed = true;
}else if(!waiting){//not yet waiting for the 15 ms
waiting = true;
tWaitStart = System.nanoTime();
}else if(System.nanoTime() - tWaitStart >= 15000000){//waiting is over
waiting = false;
if(!aPressed){//a still isn't pressed
aTruePressed = false;
}
}
}
}
};
据我所知,对布尔值进行计时是使其适用于任何操作系统的唯一方法。正如我所说,在Windows操作系统上,这不应该是(或者至少不是我上次编码的时候)。
编辑:最后,正如我忘记提到的那样,您可以再创建一个线程来监视truePressed
布尔值并相应地处理移动。
其次,只是一些建议,如果你的应用程序中有几个相关的键,我建议使用按下的布尔数组,truePressed布尔值,等待布尔值和tWaitStart long来处理一个for循环中的多个键。
第二次修改:我发现this问题与您的问题非常相似。我希望它有所帮助。
答案 1 :(得分:0)
尝试在重绘循环中的repaint()之前调用。
Toolkit.getDefaultToolkit().sync()