Java:如何在不检查每个循环的情况下检测某个键是否在某个时间内被按下

时间:2011-09-21 12:03:20

标签: java timing keyevent

编辑:注意别人,过早优化是万恶之源!如果我没有忙着尝试优化我的代码的每个方面(这是一个阶段OK!)我已经做了一个很好的,可读的程序,可以被其他人维护和理解。


每个循环(1/60秒)Player类检查Game类以查看哪个键是关闭的,如果玩家没有面向正确的方向它转向正确的方向,否则它会向那个方向移动

可悲的是,这意味着如果你想转动而不是移动,你必须按下键不到2/60秒(两个循环)。用于检查按下哪个键的代码如下 以及完整源代码和构建示例的链接。

public class Game extends RenderableObject
{
    public static final byte NONE = 0;
    public static final byte UP = 1;
    public static final byte RIGHT = 2;
    public static final byte DOWN = 3;
    public static final byte LEFT = 4;

    public byte key = NONE;

    public Game()
        {
        }

    @Override
    public void keyPressed(KeyEvent ke)
        {
            if (!paused)
                {
                    if (ke.getKeyCode() == 38) // '^ key'
                        {
                            key = UP;
                            return;
                        }
                    else if (ke.getKeyCode() == 40) // 'v key'
                        {
                            key = DOWN;
                            return;
                        }
                    if (ke.getKeyCode() == 37) // '< key'
                        {
                            key = LEFT;
                            return;
                        }
                    else if (ke.getKeyCode() == 39) // '> key'
                        {
                            key = RIGHT;
                            return;
                        }
                }
        }

    @Override
    public void keyReleased(KeyEvent ke)
        {
            if (ke.getKeyCode() == 38) // '^ key'
                {
                    if (key == UP)
                        key = NONE;
                    return;
                }
            else if (ke.getKeyCode() == 40) // 'v key'
                {
                    if (key == DOWN)
                        key = NONE;
                    return;
                }
            if (ke.getKeyCode() == 37) // '< key'
                {
                    if (key == LEFT)
                        key = NONE;
                    return;
                }
            else if (ke.getKeyCode() == 39) // '> key'
                {
                    if (key == RIGHT)
                        key = NONE;
                    return;
                }

        }

链接到完整的源代码和内置示例:(以及指向页面的链接,无论如何都有链接到下载!

警告:如果我的命名惯例不合适,我是NOOB,请不要伤害我!

http://troygametwodee.blogspot.com/2011/09/latest-build-21092011.html

所以我已经玩弄了一些想法,但没有一个看起来特别优雅,而且一切都变得非常混乱,

我理想情况下能够检查游戏类中的某种布尔值,这样当bool为真时玩家才会朝那个方向移动,但我也失败了:(

所以如果有人有任何建议我会非常高兴:)

提前感谢一堆

3 个答案:

答案 0 :(得分:2)

好的,所以我如何在保持流体运动的同时解决问题:

首先,我添加了一个名为“hold”的布尔变量。它本身就没用了所以我也补充道 一个数值变量,称为“timeHeld”。每次按下一个键,我将“timeHeld”重置为零并使其“保持”== false,并将以下代码放入我的循环中。

if (timeHeld < 20)
    timeHeld++;
else
    held = true;

所以在我的播放器类中,当决定移动它的方式时,调用“Game.key”来评估哪个键是关闭的,然后如果“hold”布尔值为真(它是在三分之一秒之后)玩家走向那个方向,否则玩家会停留在屏幕上的位置,只是改变了它看起来的方向。

这在一定程度上起作用,但每次改变方向时,“保持”变量再次设置为零。这意味着每次我转身时都会延迟三分之一秒,非常烦人!

所以我这样做了:

if (ke.getKeyCode() == 38) // '^ key'
        {
            if (key == NONE)
                {
                    held = false;
                    timeHeld = 0;
                }
            key = UP;
            return;
    }

这意味着只要箭头键向下“保持”仍然为真,所以一旦玩家移动,转弯时没有延迟。

这完全是完美无缺的,所以这就是答案,但我还添加了另一个变量。因为我在使用箭头或'wasd'键时只使用我的中指同时按下UP和DOWN键,所以当我从北向南切换时,我最终放开了所有按键。在这种情况下使用上面描述的代码我最终停止了三分之一秒来解决这个问题我添加了一个名为“延迟”的变量

当一个键被释放时,延迟被设置为10(循环),我调用的每个循环:

if (delay > 0)
    delay--;

然后当按下某个键时,我打电话给:

if (ke.getKeyCode() == 38) // '^ key'
    {
        if (key == NONE && delay == 0)
                {
                    held = false;
                        timeHeld = 0;
                }
            key = UP;
            return;
        }

这意味着当按下方向键并且在按下时没有其他方向键向下并且延迟为0时,“保持”仅被设置为假。这让我在放手之间有10个循环延迟在“hold”之前将所有箭头键和另一个箭头键设置为false。

困惑?我是!但是它有效,任何有这个问题的人都可以点击我的博客的链接,这应该有最新的工作来源,或者只是让我解释一下你没有得到的东西:D

答案 1 :(得分:1)

更清楚地描述你想要达到的目标会有所帮助。

但是,如果我理解正确,您可以保留关键字关闭的简短历史记录,例如保留最后五个循环的键值。然后,如果至少一定数量的先前值与特定键匹配,则可以执行某些操作。

答案 2 :(得分:0)

尝试为其中的所有动作/按键保持一个带有布尔值的值对象。 keydown的布尔值为true,keyup的布尔值为false。处理关键操作后,您可以仅将相关键的值对象更新为true / false。

然后,当您的游戏更新循环运行时,您可以检查当前哪些密钥已关闭。