python - Pygame 多线程

标签 python multithreading pygame

我在编写使用线程的简单 Pygame 应用程序时遇到了一些问题。请记住,这是我编写的第一个多线程代码。

情况是这样的。我正在编写一个简单的应用程序,它将在屏幕上绘制一些时髦的线条。我的问题是,当我画线时,应用程序无法处理输入,所以我不能(例如)关闭窗口,直到线完成。这是我的原始代码的样子:

import time
import pygame
from pygame.locals import *

SIZE = 800

def main():
    screen = pygame.display.set_mode((SIZE, SIZE))
    for interval in xrange(50, 1, -5):
        screen.fill((0, 0, 0))
        for i in xrange(0, SIZE, interval):
            pygame.draw.aaline(screen, (255, 255, 255), (i+interval, 0), (0, SIZE-i))
            pygame.draw.aaline(screen, (255, 255, 255), (i, 0), (SIZE, i+interval))
            pygame.draw.aaline(screen, (255, 255, 255), (SIZE, i), (SIZE-i-interval, SIZE))
            pygame.draw.aaline(screen, (255, 255, 255), (SIZE-i, SIZE), (0, SIZE-i-interval))
            pygame.display.update()
            time.sleep(0.03)
        time.sleep(3)
    while True:
        for evt in pygame.event.get():
            if evt.type == QUIT:
                return

if __name__ == '__main__':
    pygame.init()
    main()
    pygame.quit()

如您所见,事件循环仅在绘图完成时运行,因此在此之前窗口关闭按钮没有响应。我认为将绘图代码放入其自己的线程中可能会有所帮助,因此我将代码更改为:

import threading, time
import pygame
from pygame.locals import *

SIZE = 800

def draw():
    screen = pygame.display.set_mode((SIZE, SIZE))
    for interval in xrange(50, 1, -5):
        screen.fill((0, 0, 0))
        for i in xrange(0, SIZE, interval):
            pygame.draw.aaline(screen, (255, 255, 255), (i+interval, 0), (0, SIZE-i))
            pygame.draw.aaline(screen, (255, 255, 255), (i, 0), (SIZE, i+interval))
            pygame.draw.aaline(screen, (255, 255, 255), (SIZE, i), (SIZE-i-interval, SIZE))
            pygame.draw.aaline(screen, (255, 255, 255), (SIZE-i, SIZE), (0, SIZE-i-interval))
            pygame.display.update()
            time.sleep(0.03)
        time.sleep(3)

def main():
    threading.Thread(target=draw).start()
    while True:
        for evt in pygame.event.get():
            if evt.type == QUIT:
                return

if __name__ == '__main__':
    pygame.init()
    main()
    pygame.quit()

但我得到的只是一个黑屏,它也不响应输入。我在这里做错了什么?

最佳答案

虽然我从未使用过 pygame,但我怀疑您是否可以(或应该)从不同的线程调用它的 API。你所有的绘图都应该在主事件循环中完成。

我猜你必须改变你对游戏开发的思考方式。不要使用 time.sleep() 来暂停绘图,而是创建一个可以定期更新的对象。通常,这是分两次完成的——update() 及时推进对象状态,draw() 呈现对象的当前状态。在主循环的每次迭代中,更新所有对象,然后绘制所有对象。请注意,draw() 应假定屏幕为空白并绘制当前所需的每一行。

在您的简单案例中,您可以使用更简单的方法。将 draw() 函数中的 time.sleep() 替换为 yield。通过这种方式,您可以获得一个迭代器,该迭代器将产生建议的时间量以等待下一次迭代。在主循环之前,通过调用 draw() 创建一个迭代器并初始化下一次绘制应该发生的时间:

draw_iterator = draw()
next_draw_time = 0  # Draw immediately

然后,在主循环中,处理完用户输入后,检查是否到了绘制时间:

current_time = time.time()
if current_time >= next_draw_time:

如果是,运行下一次迭代并安排下一次绘制时间:

    try:
        timeout = next(draw_iterator)
    except StopIteration:
        # The drawing is finished, exit the main loop?
        break
    next_draw_time = current_time + timeout

关于python - Pygame 多线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7141665/

相关文章:

python - 如何从该列中仅提取数字?

c - 使 C 库线程安全

multithreading - 如何强制主线程等待其所有子线程在 Haskell 中完成

python - 在 Mac OS 10.13(High Sierra) 上导入 pygame 模块时遇到问题!

python - Pandas DataFrame没有属性 'is_monotonic_increasing'

python - 无法打开数据库文件 - Mayan EDMS

Python,提取标签并获取单词的位置

.net - 当互锁类可用时,为什么要在.NET中使用SyncLocks进行简单操作?

python - 在 Sprite 中向前移动

python - 使用线程在后台加载内容