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

发布于 2024-12-05 14:25:05 字数 2752 浏览 0 评论 0原文

编辑:请注意其他人,过早的优化是万恶之源!如果我没有忙着尝试优化代码的各个方面(这是一个好的阶段!),我就会编写一个漂亮的、可读的程序,可以由其他人维护和理解。


每个循环(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;
                }

        }

链接到完整的源代码和构建的示例:(无论如何,还有一个带有下载链接的页面链接!

警告:我是一个菜鸟,如果我的命名约定不正确......请不要伤害我!

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

所以我已经尝试过一些想法,但没有一个看起来特别优雅,而且都变成了非常混乱,很快,

我理想地希望能够在游戏类中检查某种布尔值,这样玩家只有在布尔值为真时才朝那个方向移动,但我失败了也是如此:(

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

提前谢谢大家

EDIT: Notice to others, premature optimisation is the root of all evil! Had I not been busily attempting to optimise every aspect of my code (it was a phase OK!) I'd have made a nice, readable program that could be maintained and understood by others.


Each loop (1/60th of a second) the Player class checks the Game class to see which key is down, If the player is not facing the right way it turns to face the right way, else it moves in that direction.

Sadly this means that if you want to turn and not move you have to tap the key for less than 2/60ths of a second (two loops). The code for checking which key is held down is below
and a link to the full source code and a built example is below that.

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;
                }

        }

Link to full source code and built example: (well a link to the page with a link to the download anyway!

WARNING: I am a NOOB, if my naming conventions are off... please don't hurt me!

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

So I have toyed with a few ideas already, but none seem particularly gracefull, and all become very messy very quickly,

I'd ideally like to be able to check some sort of boolean in the game class so the player only moves in that direction when the bool is true, but I failed at that too :(

So if anyone has any suggestions I would be very happy :)

Thanks a bunch in advance

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

断念 2024-12-12 14:25:05

好吧,那么我如何解决这个问题,同时保持流畅的运动可能:

首先,我添加了一个名为“held”的布尔变量。这本身是没有用的,所以我还添加了
一个数值变量,称为“timeHeld”。每次按下一个键时,我都会将“timeHeld”重置为零,并使“held”== 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”键演奏时,我只使用中指来操作向上和向下键,所以当我从北向南切换时,我最终会放开所有键。在这种情况下,使用如上所述的代码,我最终停止了三分之一秒,所以为了解决这个问题,我添加了一个名为“延迟”的变量

,当松开按键时,延迟设置为 10(循环),每个循环I call:

if (delay > 0)
    delay--;

then 当按下某个键时 I call:

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

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

使困惑?我是!但它有效,任何其他遇到此问题的人都可以点击我的博客的链接,该博客应该有最新的工作源代码,或者只是要求我解释你没有得到的部分:D

Ok, so how I solved the issue while keeping fluid motion possible:

First I added a boolean variable called "held". This on it's own was useless so I also added
a numerical variable, called "timeHeld". Each time a key was pressed I reset "timeHeld" to zero and made "held" == false, and put the following code into my loop.

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

So in my player class, when deciding which way to move it calls "Game.key" to asses which key is down, then if the "held" boolean is true (which it is after one third of a second) the player walks in that direction, Otherwise the player stayed where it is on screen and just changed the direction it was looking.

This worked to an extent, but each time I change direction the "held" variable was set to zero again. This means each time I turned I was delayed by a third of a second, very annoying!

So I did this:

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

this means that as long as an arrow key is down "held" remains true, so once the player gets moving there is no delay when turning a corner.

This worked absolutely perfectly as it was, so that is the answer, however I also added another variable. Because I only use my middle finger for both the UP and DOWN key while I play using the arrow or 'wasd' keys, I end up letting go of all of the keys when I switch from moving north to south. In this case with the code as described above I end up stopping for a third of a second SO to fix this I added a variable called "delay"

When a key is let go of, delay is set to 10 (loops), each loop I call:

if (delay > 0)
    delay--;

then when a key is pressed I call:

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

This means that "held" is only ever set to false when a direction key is pressed and there were no other direction keys down at the time it was pressed AND delay is 0. this gives me a 10 loop delay between letting go of all the arrow keys and pressing another one before "held" is set to false.

Confused? I am! but it works, anyone else who has this problem can either follow the link to my blog, which should have the latest working source, or just ask me to explain the bits you don't get :D

紫﹏色ふ单纯 2024-12-12 14:25:05

更清楚地描述您想要实现的目标会有所帮助。

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

A clearer description of what you are trying to achieve would help.

However, if I understand correctly, you could keep a short history of which key is down, e.g. keep the key value for the last five loops. Then you could execute certain actions if at least a certain number of the previous values match a particular key.

蓝天 2024-12-12 14:25:05

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

然后,当您的游戏更新循环运行时,您可以检查哪些键当前被按下。

try holding a value object with boolean value for all of your actions/keypresses in it. The boolean will be true for keydown and false for keyup. When the key actions are handled you can then update the value object to true/false for the relevant key only.

Then when your game update loop runs you can check which key(s) are currently down.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文