pygame:key.get_pressed()与事件队列不一致 [英] Pygame: key.get_pressed() does not coincide with the event queue

查看:412
本文介绍了pygame:key.get_pressed()与事件队列不一致的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用Python中的pygame为应用程序制定简单的控件.我已经掌握了基础知识,但是碰到了怪异的墙:我正在使用箭头键来控制角色.如果我按住一个箭头键,然后按住另一个箭头键(以对角线方向移动),则角色将按预期方式移动.但是,如果释放按下的 second 键(同时仍然按住 first 键),即使我仍然按住该第一键,角色也会停止移动.这是我的简单运动代码:

I'm attempting to work out simple controls for an application using pygame in Python. I have got the basics working, but I'm hitting a weird wall: I am using the arrow keys to control my character. If I hold down one arrow key, then hold down another arrow key (to move diagonally), the character moves as expected. However, if I release the second key that I pressed (while still holding down the first key), the character stops moving, even though I am still holding down that first key. Here is my simple movement code:

for event in pygame.event.get():
    if event.type == QUIT:
        pygame.quit()
        sys.exit()
    elif event.type == KEYDOWN:
        if pygame.key.get_pressed()[K_LEFT]:
            player.pos = (player.pos[0] - 2, player.pos[1])
        if pygame.key.get_pressed()[K_RIGHT]:
            player.pos = (player.pos[0] + 2, player.pos[1])
        if pygame.key.get_pressed()[K_UP]:
            player.pos = (player.pos[0], player.pos[1] - 2)
        if pygame.key.get_pressed()[K_DOWN]:
            player.pos = (player.pos[0], player.pos[1] + 2)

现在,我自然对此感到非常困惑.因此,我尝试打印一些行进行调试.在主控制循环的顶部,我写道:

Now, I was naturally very confused by this. So I tried to print some lines to debug. In the top of the main control loop, I wrote:

print (pygame.key.get_pressed()[K_DOWN], pygame.key.get_pressed()[K_RIGHT])
print pygame.event.get()

...以输出一个显示上下箭头键状态的元组,然后显示pygame事件队列.我的结果让我更加困惑.如果我沿对角线左右移动字符,请先按向下键,然后再按向右键,然后按然后释放右键,使其简单地向下移动,字符将像以前一样停止移动...但是这是打印到外壳上的:

...to output a tuple displaying the state of the down and right arrow keys, and then display the pygame event queue. My results baffled me even more. If I move the character diagonally down and right, pressing the down key first and then the right key, then release the right key to make it move simply downward, the character stops moving as before... but this is printed to the shell:

(1, 0)
[]

也就是说,当我释放右箭头键并仍然按住向下箭头键时,pygame.key.get_pressed()知道向下箭头键仍在按住,但是在那里在事件队列中什么都没有.

That is, when I release the right arrow key and still hold down the down arrow key, pygame.key.get_pressed() understands that the down arrow key is still being held down, but there is nothing in the event queue.

此外,在代码的前面(在控制循环之前),我正在调用

Also, earlier in the code (before the control loop) I am invoking

pygame.key.set_repeat(1, 2)

使角色在按住键的同时继续移动.

to make the character continue to move while the key is held down.

任何帮助将不胜感激!谢谢:)

Any help will be appreciated! Thanks :)

推荐答案

对于运动,您不应检查事件(例如KEYDOWNKEYUP),而应检查主循环的每个迭代(如果您有运动键)被按下(使用 get_pressed ).

For things like movement, you should not check for events (like KEYDOWN or KEYUP), but check every iteration of your mainloop if your movement keys are pressed (using get_pressed).

在代码中,仅当还有KEYDOWN事件时,才检查按下的键.

In your code, you check the pressed keys only if there's also a KEYDOWN event.

还需要考虑其他一些事情:

There are also some other things to consider:

  • 您应该将按键映射和播放器的速度分开,这样以后更改其中任何一个都将变得更加容易.

  • You should seperate the key-mapping and the speed of your player, so it will be easier later on to change either of this.

您应首先确定运动矢量并对其进行归一化,否则,如果垂直和水平运动速度为10,则对角线运动速度将为〜14.

You should determine a movement vector and normalize it first, since otherwise, if your vertical and horizontal movement speed is 10, your diagonal movement speed would be ~14.

工作示例:

import pygame

pygame.init()

screen = pygame.display.set_mode((200, 200))
run = True
pos = pygame.Vector2(100, 100)
clock = pygame.time.Clock()

# speed of your player
speed = 2

# key bindings
move_map = {pygame.K_LEFT: pygame.Vector2(-1, 0),
            pygame.K_RIGHT: pygame.Vector2(1, 0),
            pygame.K_UP: pygame.Vector2(0, -1),
            pygame.K_DOWN: pygame.Vector2(0, 1)}

while run:
  for e in pygame.event.get():
    if e.type == pygame.QUIT: run = False

  screen.fill((30, 30, 30))
  # draw player, but convert position to integers first
  pygame.draw.circle(screen, pygame.Color('dodgerblue'), [int(x) for x in pos], 10)
  pygame.display.flip()

  # determine movement vector
  pressed = pygame.key.get_pressed()
  move_vector = pygame.Vector2(0, 0)
  for m in (move_map[key] for key in move_map if pressed[key]):
    move_vector += m

  # normalize movement vector if necessary
  if move_vector.length() > 0:
    move_vector.normalize_ip()

  # apply speed to movement vector
  move_vector *= speed

  # update position of player
  pos += move_vector

  clock.tick(60)

这篇关于pygame:key.get_pressed()与事件队列不一致的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆