当前位置: 首页 > 面试题库 >

pygame:key.get_pressed()与事件队列不一致

薛楷
2023-03-14
问题内容

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

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)

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

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

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

(1, 0)
[]

也就是说,当我 松开
向右箭头键并仍然按住向下箭头键时,pygame.key.get_pressed()可以理解,向下箭头键仍处于按下状态,但是事件队列中没有任何内容。

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

pygame.key.set_repeat(1, 2)

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

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


问题答案:

对于诸如移动之类的事情,您不应该检查事件(如KEYDOWNKEYUP),而应检查主循环的每个迭代(如果按下了移动键get_pressed)(使用)。

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

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

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

  • 您应该确定运动向量并首先对其进行归一化,否则,如果您的垂直和水平运动速度为10,对角线运动速度将为〜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)


 类似资料:
  • 我刚才看到了三个方法的文档,当我们在工作线程中工作时,它们可以用来在UI线程中执行一段代码。方法有: > public final void runOnUIThread(Runnable action)-在UI线程上运行指定的操作。如果当前线程是UI线程,则立即执行该操作。如果当前线程不是UI线程,则将操作发布到UI线程的事件队列中 public boolean post(Runnable act

  • 问题内容: 我正在尝试模拟使用扭曲运行的应用程序网络。作为仿真的一部分,我希望同步某些事件,并能够为每个进程提供大量数据。我决定使用多处理事件和队列。但是,我的过程变得异常混乱。 我在下面编写了示例代码来说明问题。具体来说,(大约95%的时间是在我的沙桥机器上), “ run_in_thread”函数完成了,但是直到我按Ctrl- C之后才调用“ print_done”回调。 另外,我可以更改示例

  • 编年史队列doco指定可以在不同的盒子上有编年史接收器,事件通过网络从单个编年史队列分发到它。(http://chronicle.software/products/chronicle-queue/)

  • 问题内容: 可以以标准方式执行此操作吗? 这是场景。 开始在EDT中执行一些昂贵的操作(EDT被阻止,直到昂贵的操作结束为止)。 在阻止EDT的同时,用户继续单击/拖动鼠标按钮。所有鼠标动作都记录在某处。 当EDT免费时(用昂贵的东西完成),它开始处理鼠标事件。 我在步骤3中想要的是丢弃堆积的鼠标事件。EDT释放后,任何新的鼠标事件都应按常规方式处理。 关于如何实现这一目标的任何想法。 PS:对于

  • 问题内容: 我已经在堆栈溢出中看到了类似的问题,但是没有一个问题完全陷入我所遇到的问题吗?我熟悉事件队列,它们如何工作以及如何实现。我是Node.js的新手,我想围绕Node.js的工作方式进行总结。 在c ++应用程序中,您将按照以下方式进行操作: 现在,在使用node.js的情况下,我可能会有一个看起来像main.js的主文件。 我了解server.listen会将处理程序附加到事件队列,并且

  • 本文向大家介绍学习spring事务与消息队列,包括了学习spring事务与消息队列的使用技巧和注意事项,需要的朋友参考一下 在开发过程中,遇到一个bug,产生bug的原因是spring事务提交晚于消息队列的生产消息,导致消息队列消费消息时获取到的数据不正确。这篇文章介绍问题的产生和一步步的解决过程。 一.问题的产生: 场景还原:接口中的一个方法,首先修改订单状态,然后向消息队列中生产消息,消息队列