Pygame键盘布局混乱

7

我使用的是 Mac OS X 10.6 操作系统,在我的键盘输入选择菜单中有 Dvorak、美式扩展和挪威语,而我使用的是美式扩展。

当我运行需要键盘输入的 Pygame 程序时,无论我实际上选择了哪个输入法,pygame 都认为我正在使用 dvorak。

以下是获取键盘输入的代码:

    # Check for events
for event in pygame.event.get():
    if event.type == KEYDOWN:
        # Change the keyboard variables
        if event.key == K_LEFT or event.key == ord('a'):
            moveRight = False
            moveLeft = True
        if event.key == K_RIGHT or event.key == ord('d'):
            moveLeft = False
            moveRight = True
        if event.key == K_UP or event.key == ord('w'):
            moveDown = False
            moveUp = True
        if event.key == K_DOWN or event.key == ord('s'):
            moveUp = False
            moveDown = True
    if event.type == KEYUP:
        if event.key == K_ESCAPE:
            pygame.quit()
            sys.exit()
        if event.key == K_LEFT or event.key == ord('a'):
            moveLeft = False
        if event.key == K_RIGHT or event.key == ord('d'):
            moveRight = False
        if event.key == K_UP or event.key == ord('w'):
            moveUp = False
        if event.key == K_DOWN or event.key == ord('s'):
            moveDown = False
        if event.key == ord('x'):
            player.top = random.randint(0, WINDOWHEIGHT - player.height)
            player.left = random.randint(0, WINDOWWIDTH - player.width)

箭头键可以正常使用,但WASD键的位置与Dvorak键盘布局一致。因此,“A”在两种布局中处于相同位置,“W”位于QWERTY键盘上的逗号键上,依此类推。如果我将代码更改为查找“a”、“e”、“,”和“o”键,则可以如预期般工作。
我该如何使Pygame使用正确的布局?

1
为什么你在使用pygame提供的KEYS而不是ord()函数? - Bartlomiej Lewandowski
代码来自《用Python发明你自己的电脑游戏》一书(inventwithpython.com)。我不知道为什么作者选择使用ord()而不是KEYS。或许在下一章节或续集《用Pygame发明...》中能了解到。 - MageJohn
不好意思,实际上这个续集叫做“使用Python和Pygame制作游戏”。 - MageJohn
2个回答

3

好的,我必须做一些特殊处理才能让它工作。首先,建议使用键扫描码,可以从event.scancode获取。每个键都有一个唯一的代码,指的是键盘上的物理按键,而无论您使用的是dvorak还是us键盘布局,这个扫描码都是相同的。然后,在keydown事件中,您将拥有一个称为unicode的属性,该属性是所按下的字符,并且遵循当前正在使用的键盘布局。因此,在us布局上按下d键会得到unicode d,在dvorak上,该物理键会得到e字符,并且在event.unicode中正确反映出来。这里有一点有点烦人。似乎只有在keydown事件上才能使用unicode属性,而不是keyup事件。因此,我简单地创建了一个名为keymap的字典,将此信息作为scancode到unicode字符的映射进行跟踪。下面的示例代码将打印出您按下的字符,考虑到键盘布局。您可以尝试一下,即使在程序执行期间切换键盘布局,它仍然会选择正确的键。下面看到的输出是我在us布局中按下d键,切换到dvorak,按下相同的键并正确地得到e。使用dvorak比qwerty好多了,我也在用它:)

代码

import pygame, os
from pygame.locals import *

pygame.init()
screen = pygame.display.set_mode((640, 480))
keymap = {}

while True:
    event = pygame.event.wait()
    if event.type == KEYDOWN:
        keymap[event.scancode] = event.unicode
        print 'keydown %s pressed' % event.unicode
        if (event.key == K_ESCAPE):
            os._exit(0)

    if event.type == KEYUP:
        print 'keyup %s pressed' % keymap[event.scancode]

输出

keydown d pressed
keyup d pressed
keydown e pressed
keyup e pressed

谢谢!这个解决方案非常好用!不过我仍然想知道为什么pygame默认情况下不读取当前的键盘布局。 - MageJohn
在某种程度上,它确实提供了物理按键和布局字符。这可能是一种设计决策来实现它。尽管如此,这非常令人困惑。 - Marwan Alsabbagh

0

接受的答案是正确的,但为了简洁起见,这里是解决方案:

if event.type == pygame.KEYDOWN:
   print(event.unicode)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接