Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 用Pygame实现多线程_Python_Multithreading_Pygame - Fatal编程技术网

Python 用Pygame实现多线程

Python 用Pygame实现多线程,python,multithreading,pygame,Python,Multithreading,Pygame,我在编写一个使用线程的简单Pygame应用程序时遇到了一些问题。请记住,这是我写的第一个多线程代码 情况是这样的。我正在写一个简单的应用程序,可以在屏幕上画一些时髦的线条。我的问题是,当我绘制线条时,应用程序无法处理输入,因此(例如)在线条完成之前,我无法关闭窗口。这是我的原始代码的样子: import time import pygame from pygame.locals import * SIZE = 800 def main(): screen = pygame.displ

我在编写一个使用线程的简单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

这很有魅力。我想按照这些思路做一些事情,但我不知道如何在不重新实现整个线程模块的情况下使函数暂停。我没有想过使用迭代器。谢谢你不应该使用时间睡眠。您需要在pygame中创建一个时钟:
clock=pygame.time.clock()
,然后使用
clock.tick()
方法。阅读更多信息:@Javier:将
yield
添加到
draw()。看见