Pygame - 等待动画完成

Pygame - Wait for animation to finish

我制作了一个 Button class,它基本上绘制了一个 Rect 对象和一个文本(如果指定的话),并且我实现了一个动画,该动画基本上缩小按钮并在打开时快速膨胀它点击

class Button:
    def __init__(self, surface, pos, size, bg_color, hover_color):
        self.surface = surface
        self.x, self.y = pos[0], pos[1]
        self.width, self.height = size[0], size[1]
        self.bgColor = bg_color
        self.hoverColor = hover_color
        self.rect = pygame.Rect(pos, size)
        self.text = None
        self.clicked = False
    
    def addText(self, font, text, txt_color):
        self.text = font.render(text, True, txt_color)
        self.textRect = self.text.get_rect(center = self.rect.center)

    def update(self):
        if self.isHovered():
            pygame.draw.rect(self.surface, self.hoverColor, self.rect, border_radius=20)
        else:
            pygame.draw.rect(self.surface, self.bgColor, self.rect, border_radius=20)

        if(self.text):
            self.surface.blit(self.text, self.textRect)

        self.checkClicked()

    def checkClicked(self):
        if(self.rect.collidepoint(pygame.mouse.get_pos())):
            if(pygame.mouse.get_pressed()[0]):
                if(not self.clicked):
                    self.clicked = True
                    self.rect.inflate_ip(-7, -7)
            else:
                if(self.clicked):
                    self.clicked = False
                    self.rect.inflate_ip(7, 7)
                    
    def isHovered(self):
        return True if self.rect.collidepoint(pygame.mouse.get_pos()) else False

这可能不是最有效的方法,但我稍后会担心。

那么实施将是:

startBtn = Button(display, (100, 160), (200, 40), (40, 40, 40), (70, 70, 70))
run = True
    while run:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
            elif (event.type == pygame.MOUSEBUTTONDOWN and event.button == 1):
                if(startBtn.rect.collidepoint(pygame.mouse.get_pos())):
                    showNextScreen() # Here lies the issue
                    print('pressed')
        display.fill((50, 50, 50))
        startBtn.update()
        pygame.display.update()

我有一个函数可以绘制一个新屏幕并基本开始游戏,但是它发生得太快以至于你看不到按钮的动画,我正在努力寻找让脚本等待的方法为了让按钮动画完成然后做一些事情,我已经尝试了 pygame.time.wait()pygame.time.delay() 但整个脚本冻结并使情况变得更糟,我怎样才能做到这一点?

你可以直接使用 time.sleep()

我编写了一个名为 sleep 的函数,它会等待给定的时间而不会冻结游戏。

函数

def sleep(ms): # ms --> time in milliseconds
    start = pygame.time.get_ticks()
    running = True
    while running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit(0)

        now = pygame.time.get_ticks()
        if now - start == ms:
            running = False

说明

它有一个参数:ms,这是您希望程序等待的时间量(以毫秒为单位)(1 秒 = 1000 毫秒)。在函数中,我将一个名为 start 的变量设置为 pygame.time.get_ticks(),即 returns 当前时间。然后,在一个 while 循环中,我创建了一个事件循环来检查 pygame.QUIT 事件,这样如果用户在函数仍然是 运行 时单击 X,程序将响应并退出该程序。在事件循环之后,我将一个名为 now 的变量设置为 pygame.time.get_ticks() 以获取当前时间。然后我检查 now(当前时间)减去 start(开始时间)是否等于 ms(给定的等待时间,以毫秒为单位)。这将检查给定的时间是否已经过去。如果是,则 while 循环结束。如果不是,while 循环将保持 运行 直到条件为 True.

我找到了实现此目的的方法,同样,这可能不是最佳方法,但它确实可以:

threading 中导入 Timer 来创建一个计时器,并将绘制下一个 screen/scene 的函数作为参数传递,以将其延迟几毫秒就可以了。

#up in the script
from threading import Timer
import pygame

#then some code goes here
.
.
.
def showNextScreen():
    #code related to the next screen goes here

startBtn = Button(display, (100, 160), (200, 40), (40, 40, 40), (70, 70, 70))
run = True
    while run:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
            elif (event.type == pygame.MOUSEBUTTONDOWN and event.button == 1):
                if(startBtn.rect.collidepoint(pygame.mouse.get_pos())):
                    t = Timer(0.3, showNextScreen) #Timer(seconds, function)
                    t.start() #starts the timer and once its over it calls the function passed
                    #giving the button animation enough time to fully finish.
                    print('pressed')
        display.fill((50, 50, 50))
        startBtn.update()
        pygame.display.update()