Python Pygame 俄罗斯方块,按键处理问题。实施延迟自动换档。移动前必须按下一个键多长时间
Python Pygame Tetris, problems with handling of keypresses. implement delayed auto shift. how long a key has to be pressed before moving
我想编写自己的俄罗斯方块。目标是尽可能接近这个游戏:https://jstris.jezevec10.com/?play=1&mode=1
我不知道我是否 google 做错了,但我找不到满意的答案。
问题:
棋子可以随着箭头左右移动。如果玩家按一次键,棋子应该向左或向右移动 1。现在我想实现在一定时间后(t > 133ms - 默认设置 jstris),作品应该直接移动到屏幕的一侧。与其说是按键事件,不如说是按键事件。
1)
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
piece.x -= 1
如果这样做,玩家将无法按住左箭头。他必须一遍又一遍地按它才能到达屏幕的一侧。
2)
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
piece.x -= 1
在此解决方案中,实现了将不断移动的棋子移到一边的目标,但几乎不可能只将棋子移动 1。
要处理这个问题,我必须设置一个低 fps 来控制是否移动 1 或更多,但这是一个非常糟糕的解决方案。大大拖慢了游戏速度,有卡顿的感觉。
那么问题来了:
如果按下键,是否可以将棋子移动 1,但如果按下键的时间超过 t>133ms,则检查实时。如果为真,则该作品应立即移动到墙上。在俄罗斯方块中,它被称为自动延迟移位 (DAS)。
这将是 1) 和 2) 的混合,由测量时间决定。
在这里发帖之前,我阅读了很多关于测量按键持续时间或事件之间时间的内容,但在这里我没有 KEYDOWN 和 KEYUP 来测量它们之间的时间,因为 KEYUP 事件甚至不存在游戏需要决定做什么。
我是否需要退出 pygame 并搜索其他模块以实现我的目标,或者我是否遗漏了什么?
感谢您的帮助!
您需要在按下按钮后寻找一段时间。使用 pygame.time.get_ticks()
to get the number of milliseconds since pygame.init()
被调用。计算按钮按下后下次可以按下的时间。如果尚未到达时间点,则放弃按键:
next_key_left_time = 0
# application loop
while True:
current_time = pygame.time.get_ticks()
# [...]
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT] and current_time >= next_key_left_time:
piece.x -= 1
next_key_left_time = current_time + 133 # 133 milliseconds
# [...]
pygame.key.get_pressed()
returns a sequence with the state of each key. If a key is held down, the state for the key is True
, otherwise False
. Use pygame.key.get_pressed()
评估按钮的当前状态并获得连续移动。因此,您可以按住该键,方块每0.133秒移动一步。
您可以使用 pygame.key.set_repeat
docs 使 KEYDOWN
事件在按住该键时重复。
尝试将以下内容放在程序的开头:
KEY_DELAY = 100
KEY_INTERVAL = 50
pygame.key.set_repeat(KEY_DELAY, KEY_INTERVAL)
如果按住某个键 100 毫秒,俄罗斯方块块将移动第二次,然后在 50 毫秒后再次移动。根据需要调整值。
我想编写自己的俄罗斯方块。目标是尽可能接近这个游戏:https://jstris.jezevec10.com/?play=1&mode=1
我不知道我是否 google 做错了,但我找不到满意的答案。
问题: 棋子可以随着箭头左右移动。如果玩家按一次键,棋子应该向左或向右移动 1。现在我想实现在一定时间后(t > 133ms - 默认设置 jstris),作品应该直接移动到屏幕的一侧。与其说是按键事件,不如说是按键事件。
1)
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
piece.x -= 1
如果这样做,玩家将无法按住左箭头。他必须一遍又一遍地按它才能到达屏幕的一侧。
2)
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
piece.x -= 1
在此解决方案中,实现了将不断移动的棋子移到一边的目标,但几乎不可能只将棋子移动 1。 要处理这个问题,我必须设置一个低 fps 来控制是否移动 1 或更多,但这是一个非常糟糕的解决方案。大大拖慢了游戏速度,有卡顿的感觉。
那么问题来了: 如果按下键,是否可以将棋子移动 1,但如果按下键的时间超过 t>133ms,则检查实时。如果为真,则该作品应立即移动到墙上。在俄罗斯方块中,它被称为自动延迟移位 (DAS)。 这将是 1) 和 2) 的混合,由测量时间决定。
在这里发帖之前,我阅读了很多关于测量按键持续时间或事件之间时间的内容,但在这里我没有 KEYDOWN 和 KEYUP 来测量它们之间的时间,因为 KEYUP 事件甚至不存在游戏需要决定做什么。
我是否需要退出 pygame 并搜索其他模块以实现我的目标,或者我是否遗漏了什么?
感谢您的帮助!
您需要在按下按钮后寻找一段时间。使用 pygame.time.get_ticks()
to get the number of milliseconds since pygame.init()
被调用。计算按钮按下后下次可以按下的时间。如果尚未到达时间点,则放弃按键:
next_key_left_time = 0
# application loop
while True:
current_time = pygame.time.get_ticks()
# [...]
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT] and current_time >= next_key_left_time:
piece.x -= 1
next_key_left_time = current_time + 133 # 133 milliseconds
# [...]
pygame.key.get_pressed()
returns a sequence with the state of each key. If a key is held down, the state for the key is True
, otherwise False
. Use pygame.key.get_pressed()
评估按钮的当前状态并获得连续移动。因此,您可以按住该键,方块每0.133秒移动一步。
您可以使用 pygame.key.set_repeat
docs 使 KEYDOWN
事件在按住该键时重复。
尝试将以下内容放在程序的开头:
KEY_DELAY = 100
KEY_INTERVAL = 50
pygame.key.set_repeat(KEY_DELAY, KEY_INTERVAL)
如果按住某个键 100 毫秒,俄罗斯方块块将移动第二次,然后在 50 毫秒后再次移动。根据需要调整值。