有效的键盘输入处理

发布于 2024-07-09 11:03:17 字数 694 浏览 8 评论 0原文

实现键盘处理的好方法是什么? 在任何语言中,当我编写键盘交互程序(例如俄罗斯方块游戏)时,我最终都会得到一些如下所示的代码:(

for event in pygame.event.get():
    if event.type == KEYDOWN:
        if False: pass          #make everything an elif
        elif rotating: pass
        elif event.key == K_q:
        elif event.key == K_e:
        elif event.key == K_LEFT:
            curpiece.shift(-1, 0)
            shadowpiece = curpiece.clone(); setupshadow(shadowpiece)
        elif event.key == K_RIGHT:
            curpiece.shift(1, 0)
            shadowpiece = curpiece.clone(); setupshadow(shadowpiece)

缩短)。 我不喜欢这个,因为这必须进入我的主循环,并且它会扰乱程序的所有部分。 这也使得用户无法在配置屏幕上更改哪个键映射到哪个操作。 是否有一个好的模式可以使用某种形式的函数回调来做到这一点?

What is a good way to implement keyboard handling? In any language, where I write a keyboard-interactive program (such as a tetris game), I end up having some code that looks like this:

for event in pygame.event.get():
    if event.type == KEYDOWN:
        if False: pass          #make everything an elif
        elif rotating: pass
        elif event.key == K_q:
        elif event.key == K_e:
        elif event.key == K_LEFT:
            curpiece.shift(-1, 0)
            shadowpiece = curpiece.clone(); setupshadow(shadowpiece)
        elif event.key == K_RIGHT:
            curpiece.shift(1, 0)
            shadowpiece = curpiece.clone(); setupshadow(shadowpiece)

(shortened). I don't like this, as this has to go in my main loop, and it messes with all parts of the program. This also makes it impossible to have a user config screen where they can change which key maps to which action. Is there a good pattern to do this using some form of function callbacks?

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

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

发布评论

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

评论(3

落在眉间の轻吻 2024-07-16 11:03:17

您可以创建一个字典,其中键是输入,值是处理按键的函数:

def handle_quit():
  quit()

def handle_left():
    curpiece.shift(-1, 0)
    shadowpiece = curpiece.clone(); setupshadow(shadowpiece)

def handle_right():
    curpiece.shift(1, 0)
    shadowpiece = curpiece.clone(); setupshadow(shadowpiece)

def handle_pause():
    if not paused:
        paused = True

branch = {
  K_q: handle_quit
  K_e: handle_pause
  K_LEFT: handle_left
  K_RIGHT: handle_right
}

for event in pygame.event.get():
    if event.type == KEYDOWN:
        branch[event.key]()

然后更改键就是修改字典的键。

You could create a dictionary where the keys are the input and the value is a function that handles the keypress:

def handle_quit():
  quit()

def handle_left():
    curpiece.shift(-1, 0)
    shadowpiece = curpiece.clone(); setupshadow(shadowpiece)

def handle_right():
    curpiece.shift(1, 0)
    shadowpiece = curpiece.clone(); setupshadow(shadowpiece)

def handle_pause():
    if not paused:
        paused = True

branch = {
  K_q: handle_quit
  K_e: handle_pause
  K_LEFT: handle_left
  K_RIGHT: handle_right
}

for event in pygame.event.get():
    if event.type == KEYDOWN:
        branch[event.key]()

Then changing the keys is a matter of modifying keys of the dictionary.

伤痕我心 2024-07-16 11:03:17

除了superjoe30的答案之外,您还可以使用两级映射(两个字典)

  • 键=> 命令串
  • 命令串 => 我认为

这将使用户定义映射变得更容易。 即用户可以将其按键映射到“命令”而不是“函数名称”

in addition to superjoe30's answer, you can use two levels of mapping (two dictionaries)

  • key => command string
  • command string => function

I think this would make it easier to allow user-defined mappings. i.e. so users can map their keys to "commands" rather than "the name of a function"

赠佳期 2024-07-16 11:03:17

我现在所做的是拥有某种输入收集类/函数/线程,它将检查预定义的键->事件绑定的列表。

像这样的事情:

class InputHandler:
    def __init__ (self, eventDispatcher):
        self.keys = {}
        self.eventDispatcher = eventDispatcher
    def add_key_binding (self, key, event):
        self.keys.update((key, event,))
    def gather_input (self):
        for event in pygame.event.get():
            if event.type == KEYDOWN:
                event = self.keys.get(event.key, None)
                if not event is None:
                    self.eventDispatcher.dispatch(event)

....
inputHandler = InputHandler(EventDispatcher)
inputHandler.add_key_binding(K_q, "quit_event")
...
inputHandler.gather_input()
....

这基本上就是 superjoe30 正在做的事情,除了我不是直接调用回调,而是通过使用事件调度系统添加另一个级别的分离,以便任何关心按下的键的代码只需侦听该事件。

此外,键可以轻松绑定到不同的事件,这些事件可以从配置文件或其他内容中读取,并且任何未绑定到事件的键都会被忽略。

What I do nowadays is have some sort of input gathering class/function/thread which will check a list of predefined key->event bindings.

Something like this:

class InputHandler:
    def __init__ (self, eventDispatcher):
        self.keys = {}
        self.eventDispatcher = eventDispatcher
    def add_key_binding (self, key, event):
        self.keys.update((key, event,))
    def gather_input (self):
        for event in pygame.event.get():
            if event.type == KEYDOWN:
                event = self.keys.get(event.key, None)
                if not event is None:
                    self.eventDispatcher.dispatch(event)

....
inputHandler = InputHandler(EventDispatcher)
inputHandler.add_key_binding(K_q, "quit_event")
...
inputHandler.gather_input()
....

It's basically what superjoe30 is doing, except that instead of calling callbacks directly, I add another level of separation by using an event dispatching system, so that any code that cares about the keys being pressed simply listen for that event.

Also, keys can be easily bound to different events, which could be read from a config file or something and any key which is not bound to an event is simply ignored.

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