2 回答

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