我是 pygame 社区和 python 的新手。对于我的计算机作业,我们必须制作一个视频游戏。我想做的是有一个循环,它首先获取用户输入,然后获取该用户输入,然后基于该输入显示一个新 View 。我试图制作一个主菜单屏幕,用户可以按向上和向下箭头来选择屏幕上的选项。然而,当我运行它时,它非常出问题,并且对用户输入的响应速度很慢。只有当你按住它时它才会移动,但它会一直到第四个选项。
while Loop_2 == True:
pygame.time.delay(75)
#Checks what keys have been pressed
keys = pygame.key.get_pressed()
#Checks if player has pressed the exit button
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
#Checks if the player has pressed escape and will end python
if keys[pygame.K_ESCAPE]:
pygame.quit()
#The second main menu if statements for moving the curser and selecting
if keys[pygame.K_DOWN] and Position < 4:
#If the player presses the down arrow to move the pointer and its not in the 4th position at the bottom. it will move down
Position = Position + 1
else:
if keys[pygame.K_UP] and Position > 1:
#If the player presses the up arrow to move the pointer and its not in the 1st position at the top. it will move up
Position = Position - 1
else:
if keys[pygame.K_LSHIFT]:
Loop_3 = True
if Position == 1:
Play_Menu()
elif Position == 2:
Saves_Menu()
elif Position == 3:
Settings_Menu()
elif Position == 4:
Quit_Menu()
#Loads the second main Menu
window.blit(main_menu_2,(0,0))
if Position == 1:
window.blit(main_menu_pointer,(650,-525))
elif Position == 2:
window.blit(main_menu_pointer,(650,-385))
elif Position == 3:
window.blit(main_menu_pointer,(650,-240))
elif Position == 4:
window.blit(main_menu_pointer,(650,-100))
pygame.display.update()
我尝试将 pygame.delay 更改为不同的值,它要么使其响应过于灵敏,要么不响应。我只是想要它,以便我可以向下或向上按下,当松开它时,它将移至下一个选项,而不是一直向下移动到底部。我在这个网站上找不到任何关于此的信息。谢谢
最佳答案
核心问题是您希望能够循环浏览菜单选项,但又不会对普通人来说太快。
当前代码正在延迟整个程序以保持速度。但这里真正需要的是对选择下一个项目之间的时间进行限制。
执行此操作的一种方法是查看 Pygame Time当选择“事件”发生时。也就是说,用户在什么时间突出显示菜单项。一个方便的时间函数是.get_ticks()
,它返回毫秒相对时间。
# user just changed selection
time_now = pygame.time.get_ticks()
这使我们能够创建一个 future 时间,之后允许进行新的选择。
# user just changed selection
time_now = pygame.time.get_ticks()
next_allowed = time_now + 300 # 300 milliseconds in the future
现在,当用户尝试更改选择时,在当前时间超过将来的这个时间之前不允许这样做。根据我们的示例,这不会再持续 300 毫秒(这相当慢)。
# user has tried to change selection
time_now = pygame.time.get_ticks()
if ( time_now > next_allowed ):
# ( TODO - menu selection change code )
next_allowed = time_now + 300 # future time next change allowed
当然,我们应该为时间延迟设置一个常量,这样就可以轻松更改它,而无需在代码中寻找常量
MENU_DELAY = 300
...
next_allowed = time_now + MENU_DELAY # future time next change allowed
下面是一些实现此类菜单的示例代码:
import pygame
WIDTH = 500
HEIGHT= 500
FPS = 60
MENU_DELAY = 200
BLACK = ( 0, 0, 0)
WHITE = (255, 255, 255)
GREEN = ( 20, 180, 20)
pygame.init()
screen = pygame.display.set_mode( ( WIDTH, HEIGHT ) )
pygame.display.set_caption( "Menuosity" )
font = pygame.font.Font( None, 32 ) # font used to make menu Items
class MenuItem:
""" Simple sprite-like object representing a Menu Button """
def __init__( self, label ):
super().__init__()
self.image = pygame.Surface( ( 200, 50 ) ) # long rectangle
self.rect = self.image.get_rect()
self.label = label.strip().capitalize()
self.selected = False
self.fore = BLACK
self.back = WHITE
self.makeImage( self.fore, self.back )
def makeImage( self, foreground, background ):
""" Make the image used for the menu item, in the given colour """
self.image.fill( background )
pygame.draw.rect( self.image, foreground, [0, 0, self.image.get_width(), self.image.get_height()], 3 )
# centred text for Label
text = font.render( self.label, True, foreground )
text_centre_rect = text.get_rect( center = self.image.get_rect().center )
self.image.blit( text, text_centre_rect )
def moveTo( self, x, y ):
""" Reposition the menu item """
self.rect.x = x
self.rect.y = y
def makeSelected( self, selected=True ):
""" If the button is selected, invert it's colours """
if ( self.selected != selected ):
# Only re-generate if different
if ( selected ):
self.makeImage( self.back, self.fore ) # inverted colours on selection
else:
self.makeImage( self.fore, self.back ) # non-selected, normal colours
self.selected = selected
def draw( self, surface ):
""" Paint the item on the given surface """
surface.blit( self.image, self.rect )
### Create a Menu of Items
menu = []
menu.append( MenuItem( "First Item" ) )
menu.append( MenuItem( "Second Item" ) )
menu.append( MenuItem( "Third Item" ) )
menu.append( MenuItem( "Fourth Item" ) )
### Highlight the first item
current_option = 0
menu[0].makeSelected()
### Lay-out the menu
for i,item in enumerate( menu ):
item.moveTo( 150, 50 + ( i * 80 ) ) # spread out in a single column
### Used to slow down the UI Changes
clock = pygame.time.Clock()
next_change_time = 0
###
### MAIN
###
while True:
time_now = pygame.time.get_ticks() # milliseconds elapsed time
# Handle events
keys = pygame.key.get_pressed()
for event in pygame.event.get():
if event.type == pygame.QUIT:
exit()
# if the user pressed [space]
if ( keys[pygame.K_SPACE] ):
# When space is pushed move to the next item, but not more than every 300ms
# So, has enough time elapsed since the last keypress?
if ( time_now > next_change_time ):
# enough time elapsed, un-select the current, and select the next menu-item
menu[current_option].makeSelected( False )
current_option += 1
if ( current_option >= len( menu ) ):
current_option = 0
menu[current_option].makeSelected( True )
next_change_time = time_now + MENU_DELAY # remember the time of the change
# paint the screen
screen.fill( GREEN ) # paint background
# Paint the menu
for item in menu:
item.draw( screen );
pygame.display.flip()
clock.tick( FPS ) # keep a sane frame-rate
关于python - 如何停止用户输入和 pygame 显示之间的滞后,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72195438/