python - 我在 pygame 中的事件循环有问题
问题描述
我正在制作一个游戏,其中玩家始终处于中间,并且背景移动以使其看起来像是玩家在移动。当我按两个箭头键时,例如。向上和向右,它对角线,但是当我放开向上箭头时,它应该继续向右。有时它可以工作,但大多数情况下它只是停止移动。
我不知道如何解决这个问题。
事件循环
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
key = pygame.key.get_pressed()
if key[K_UP]:
if key[K_RIGHT]:
bg.move("up_right")
elif key[K_LEFT]:
bg.move("up_left")
else:
bg.move("up")
elif key[K_DOWN]:
if key[K_RIGHT]:
bg.move("down_right")
elif key[K_LEFT]:
bg.move("down_left")
else:
bg.move("down")
elif key[K_RIGHT]:
if key[K_DOWN]:
bg.move("down_right")
elif key[K_UP]:
bg.move("up_right")
else:
bg.move("right")
elif key[K_LEFT]:
if key[K_DOWN]:
bg.move("down_left")
elif key[K_UP]:
bg.move("up_left")
else:
bg.move("left")
移动
这里的运动发生了变化
def move(self, direction):
if direction == "up_right":
self.posY += self.speed
self.posX -= self.speed
if direction == "up_left":
self.posY += self.speed
self.posX += self.speed
if direction == "down_right":
self.posY -= self.speed
self.posX -= self.speed
if direction == "down_left":
self.posY -= self.speed
self.posX += self.speed
if direction == "up":
self.posY += self.speed+2
if direction == "down":
self.posY -= self.speed+2
if direction == "right":
self.posX -= self.speed+2
if direction == "left":
self.posX += self.speed+2
起初,我没有添加“up_left”等,因为我认为它只会通过两个 if 并编辑两者的位置。但它没有。
很抱歉,如果这个主题已经有答案,但我找不到任何答案。
谢谢
解决方案
您的主要问题是您检查事件循环中的按键:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# only executed if there's an event returned by pygame.event.get()
# and possible executed multiple times per frame
key = pygame.key.get_pressed()
if key[K_UP]:
...
因此,执行移动 ( if key[K_UP]: ...
) 的代码仅在队列中当前有事件时执行。
只需将此代码移到事件处理程序循环之外:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# always executed every frame
key = pygame.key.get_pressed()
if key[K_UP]:
...
恕我直言,处理运动的更好方法是使用矢量,因为它们可以轻松确保恒定的运动速度并且代码少得多。
这是一个简单的例子:
import pygame
def main():
pygame.init()
screen = pygame.display.set_mode((500, 500))
clock = pygame.time.Clock()
dt = 0
movement = {
pygame.K_UP: ( 0, -1),
pygame.K_DOWN: ( 0, 1),
pygame.K_LEFT: (-1, 0),
pygame.K_RIGHT: ( 1, 0)
}
pos = pygame.Vector2((100, 100))
while True:
events = pygame.event.get()
for e in events:
if e.type == pygame.QUIT:
return
pressed = pygame.key.get_pressed()
# calculate the movement vector
move = pygame.Vector2()
for dir in (movement[key] for key in movement if pressed[key]):
move += dir
if move.length() > 0: move.normalize_ip()
# ensure we have a constant speed
pos += move * dt/5
screen.fill(pygame.Color('grey'))
pygame.draw.circle(screen, pygame.Color('dodgerblue'), [int(x) for x in pos], 20, 0)
pygame.display.update()
dt = clock.tick(60)
if __name__ == '__main__':
main()
推荐阅读
- php - 使用 PHP printf 和 sprintf 函数在文本字符串中输出动态电子邮件 mailto 链接
- assembly - 递归斐波那契 NASM
- pytorch - 将 pytorch 转换为 CoreML 时可以控制输出吗?
- git - Git 中的所有内容都显示为“新文件”
- html - #icon:hover + #text 过渡 for + #text 部分
- android - 如何在 Jetpack Compose 中为 NavigationDrawer 设置宽度和高度
- excel - ExportasFixedformat 在 900 次运行期间抛出错误 1004 一到五次
- go - 为什么 -2 和 -1 在 Go 中等于 -2?
- javascript - 如何从日期范围和持续时间中获取所有工作日
- excel - 为什么 DAX 不允许使用“==”运算符?