Pygame 的线程问题

我正在开发一个用于学习目的的小游戏。我为标题画面创建了一个简单的动画。由于代码中还有一个全屏功能,我想创建一个标题屏幕:


显示动画

当按键被激活时变成全屏

在激活全屏之前的点继续动画

为了做到这一点,我求助于threading. 然而,这是我第一次尝试做任何多线程,我不知道我做错了什么。结果是一个未确定的错误。


标题画面的代码是这样的:


try:

    GameAnimation = threading.Thread(target=GameTitleAnimation, (Window, WindowDimensions, FontDictionary, CurrentVersion))

    GameAnimation.start()

except:

    print "There was an error while loading the screen. Press one key to exit the program."

while True:

    for event in pygame.event.get():

        if event.type == pygame.QUIT:

            Quit()

        if event.type == pygame.KEYDOWN:

            if event.key == K_ESCAPE:

                Quit()

            elif event.key == K_f:

                Fullscreen(Window, WindowDimensions)

            else:

                return

动画的代码是:


TitleWhite = [255, 255, 255, 0]

Black = BASE_BLACK

TitleLetters = ("R", "O", "G", "U", "E", " ", "H", "U", "N", "T", "E", "R")

Title = FontDictionary["TitleFont"][1].render("ROGUE HUNTER", False, TitleWhite)

TextWidth = Title.get_width()

TextHeight = Title.get_height()

TitleXPosition = (WindowDimensions[0] - TextWidth) / 2

TitleYPosition = (WindowDimensions[1] / 2) - (TextHeight / 2)

for letter in TitleLetters:

    if letter == " ":

       TitleXPosition += CurrentLetterWidth

    else:

        while TitleWhite[3] < 100:

            TitleWhite[3] += 1

            CurrentLetter = FontDictionary["TitleFont"][1].render(letter, False, TitleWhite)

            CurrentLetter.set_alpha(TitleWhite[3])

            Window.blit(CurrentLetter, (TitleXPosition, TitleYPosition))

            time.sleep(0.008)

            try: 

                pygame.display.update()

            except Exception:

                traceback.print_exception

如果有人能帮助我解决这个问题,我将不胜感激。我快疯了。


陪伴而非守候
浏览 129回答 2
2回答

慕姐8265434

没有理由在您的代码中使用线程。它只会让你的代码更难阅读、更难调试和容易出错。通常,您希望在游戏中使用某种状态来确定帧中应该发生什么。您可以在此处找到基于类的示例。处理此问题的另一种方法与您的代码有点相似,是使用协程。查看您的动画代码,而不是调用pygame.display.update(),而是将控制权交还给主循环。主循环将处理事件、帧限制和绘图,然后将控制权交还给协程(它跟踪自己的状态)。这是一个简单的hacky示例:import pygameimport pygame.freetypepygame.init()size = (640, 480)screen = pygame.display.set_mode(size)clock = pygame.time.Clock()def game_state(surf):&nbsp; &nbsp; rect = pygame.Rect(200, 200, 32, 32)&nbsp; &nbsp; while True:&nbsp; &nbsp; &nbsp; &nbsp; events = yield&nbsp; &nbsp; &nbsp; &nbsp; pressed = pygame.key.get_pressed()&nbsp; &nbsp; &nbsp; &nbsp; x = 1 if pressed[pygame.K_RIGHT] else -1 if pressed[pygame.K_LEFT] else 0&nbsp; &nbsp; &nbsp; &nbsp; rect.move_ip(x*5, 0)&nbsp; &nbsp; &nbsp; &nbsp; pygame.draw.rect(surf, pygame.Color('dodgerblue'), rect)&nbsp; &nbsp; &nbsp; &nbsp; yielddef title_state(surf):&nbsp; &nbsp; text = 'Awesome Game'&nbsp; &nbsp; colors = [[255, 255, 255, 20] for letter in text]&nbsp; &nbsp; font = pygame.freetype.SysFont(None, 22)&nbsp; &nbsp; font.origin = True&nbsp; &nbsp; while True:&nbsp; &nbsp; &nbsp; &nbsp; for color in colors:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; color[3] += 33&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if color[3] > 255: color[3] = 0&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; x = 200&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for (letter, c) in zip(text, colors):&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; bounds = font.get_rect(letter)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; font.render_to(surf, (x, 100), letter, c)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; x += bounds.width + 1&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; font.render_to(surf, (180, 150), 'press [space] to start', pygame.Color('grey'))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; events = yield&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; yielddef main():&nbsp; &nbsp; title = title_state(screen)&nbsp; &nbsp; game = game_state(screen)&nbsp; &nbsp; state = title&nbsp; &nbsp; while True:&nbsp; &nbsp; &nbsp; &nbsp; events = pygame.event.get()&nbsp; &nbsp; &nbsp; &nbsp; for e in events:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if e.type == pygame.QUIT:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if e.type == pygame.KEYDOWN:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if e.key == pygame.K_ESCAPE:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if e.key == pygame.K_SPACE:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; state = game if state == title else title&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if e.key == pygame.K_f:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if screen.get_flags() & pygame.FULLSCREEN:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pygame.display.set_mode(size)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pygame.display.set_mode(size, pygame.FULLSCREEN)&nbsp; &nbsp; &nbsp; &nbsp; screen.fill(pygame.Color('grey12'))&nbsp; &nbsp; &nbsp; &nbsp; next(state)&nbsp; &nbsp; &nbsp; &nbsp; state.send(events)&nbsp; &nbsp; &nbsp; &nbsp; pygame.display.update()&nbsp; &nbsp; &nbsp; &nbsp; clock.tick(60)if __name__ == '__main__':&nbsp; &nbsp; main()看看主循环是如何干净和简单的,所有的游戏状态都是在协程中处理的。代码的标题画面部分不关心是否全屏或如何切换到全屏,主循环不关心标题画面协程做什么。而且我们不需要线程。在此处输入图片说明实际上,它与我上面链接的基于类的示例没有什么不同,但是使用协程可以轻松实现标题屏幕动画。基本上你有一个无限循环,你改变一些状态(比如字母的颜色),然后说“现在画这个!” 只需调用yield.
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python