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 3.x 使用pygame进行多线程处理,程序崩溃_Python 3.x_Multithreading_Pygame - Fatal编程技术网

Python 3.x 使用pygame进行多线程处理,程序崩溃

Python 3.x 使用pygame进行多线程处理,程序崩溃,python-3.x,multithreading,pygame,Python 3.x,Multithreading,Pygame,大家好,提前感谢你们的帮助。我刚刚发现了pygame(python的一个库),我想用它玩一玩,但我面临一个问题。我试图在代码中使用线程,但每次启动时程序都会崩溃 我已经隔离了这个问题,我知道是thread_1导致了崩溃,因为当我把它注释掉时,一切都再次正常了。我试图更改线程1函数的代码,但它仍然崩溃。我很确定导致崩溃的不是函数animateTile的内容,而是我使用线程的方式 import pygame from pygame.locals import * from threading i

大家好,提前感谢你们的帮助。我刚刚发现了pygame(python的一个库),我想用它玩一玩,但我面临一个问题。我试图在代码中使用线程,但每次启动时程序都会崩溃

我已经隔离了这个问题,我知道是
thread_1
导致了崩溃,因为当我把它注释掉时,一切都再次正常了。我试图更改
线程1
函数的代码,但它仍然崩溃。我很确定导致崩溃的不是函数
animateTile
的内容,而是我使用线程的方式

import pygame

from pygame.locals import *

from threading import Thread


def encadre(screen):  
    pygame.draw.line(screen, (250, 250, 250), (230, 140), (520, 140), 3)
    pygame.draw.line(screen, (250, 250, 250), (230, 190), (520, 190), 3)
    pygame.draw.line(screen, (250, 250, 250), (230, 140), (230, 190), 3)
    pygame.draw.line(screen, (250, 250, 250), (520, 140), (520, 190), 3)


def initRoad(screen):  
    pygame.draw.line(screen, (250, 250, 250), (30, 0), (30, 500))
    pygame.draw.line(screen, (250, 250, 250), (100, 0), (100, 500))
    pygame.draw.line(screen, (250, 250, 250), (650, 0), (650, 500))
    pygame.draw.line(screen, (250, 250, 250), (720, 0), (720, 500))
    drawLines(screen)


def drawLines(screen): 
    i = 0
    while i <= 49:
        pygame.draw.line(screen, (250, 250, 250), (65, i * 10), (65, (i + 1) * 10))
        pygame.draw.line(screen, (250, 250, 250), (685, i * 10), (685, (i + 1) * 10))
        i = i + 3


def initText(screen, text1):  
    text1pos = text1.get_rect()
    text1pos.x = 235
    text1pos.y = 150
    screen.blit(text1, text1pos)

    font1 = pygame.font.Font(None, 30)
    text1 = font1.render("PLAY", 1, (10, 10, 10))
    text1pos = text1.get_rect()
    text1pos.x = 210
    text1pos.y = 310
    screen.blit(text1, text1pos)

    font1 = pygame.font.Font(None, 30)
    text1 = font1.render("QUIT", 1, (10, 10, 10))
    text1pos = text1.get_rect()
    text1pos.x = 490
    text1pos.y = 310
    screen.blit(text1, text1pos)


def animateRoad(screen):  # not done
    pygame.draw.line(screen, (130, 130, 130), (65, 0), (65, 500))
    pygame.draw.line(screen, (130, 130, 130), (685, 0), (685, 500))


def animateTitle(screen, text1): 
    text1pos = text1.get_rect()
    while True:
        pygame.draw.rect(screen, (130, 130, 130), (235, 150, 283, 35))
        pygame.display.flip()
        pygame.time.wait(500)
        text1pos.x = 235
        text1pos.y = 150
        screen.blit(text1, text1pos)
        pygame.display.flip()
        pygame.time.wait(1000)


def loop(surface1, surface2):
    while True:
        for event in pygame.event.get():

            if event.type == QUIT:
                return

            if event.type == pygame.MOUSEBUTTONDOWN:
                if surface1.topleft[0] <= pygame.mouse.get_pos()[0] <= surface1.topright[0]:
                    if surface1.topleft[1] <= pygame.mouse.get_pos()[1] <= surface1.bottomleft[1]:
                    print('play')

                if surface2.topleft[0] <= pygame.mouse.get_pos()[0] <= surface2.topright[0]:
                    if surface2.topleft[1] <= pygame.mouse.get_pos()[1] <= surface2.bottomleft[1]:
                    return

    pygame.display.flip()
    pygame.time.wait(10)


def main():
    pygame.init()
    screen = pygame.display.set_mode((750, 500))
    pygame.display.set_caption('Infinite circle run')

    background = pygame.Surface(screen.get_size())  
    background = background.convert()
    background.fill((130, 130, 130))
    screen.blit(background, (0, 0))

    encadre(screen)
    initRoad(screen)

    surface1 = pygame.Rect(193, 290, 85, 50) 
    button1 = pygame.draw.rect(screen, (0, 0, 240), surface1)
    surface2 = pygame.Rect(472, 290, 85, 50)  
    button2 = pygame.draw.rect(screen, (240, 0, 0), surface2)

    font1 = pygame.font.Font(None, 50)
    text1 = font1.render("Infinite circle run", 1, (0, 240, 0))
    initText(screen, text1)  

    pygame.display.flip()

    thread_1 = Thread(target=animateTitle(screen, text1), daemon=True)
    thread_2 = Thread(target=loop(surface1, surface2))
    # thread_3 = Thread(target=animateRoad(screen))

    thread_1.start()
    thread_2.start()
    # thread_3.start()


if __name__ == '__main__':
    main()
导入pygame
从pygame.locals导入*
从线程导入线程
def封装(屏幕):
pygame.draw.line(屏幕,(250250250),(230140),(5201440),3)
pygame.draw.line(屏幕,(250250250),(230190),(520190),3)
pygame.draw.line(屏幕,(250250250),(230140),(230190),3)
pygame.draw.line(屏幕,(250250250),(520140),(520190),3)
def初始道路(屏幕):
pygame.draw.line(屏幕,(250250250),(30,0),(30500))
pygame.draw.line(屏幕,(250250250),(100,0),(100500))
pygame.draw.line(屏幕,(250250250),(650,0),(650500))
pygame.draw.line(屏幕,(250250250),(7200),(720500))
抽绳(屏幕)
def抽绳(屏幕):
i=0

而线程会导致许多问题,一般的经验法则是,如果没有必要,就避免它们。它们使您的程序变得不确定,更难调试,更难测试,更难维护和更慢(大多数情况下)。在您的程序中,没有理由使用线程。相反,你应该按顺序做事。Pygame将在必要时隐式创建线程(例如处理
Pygame.mixer

为什么它不起作用,是因为pygame期望所有事件处理都发生(pygame使用SDL2,因此使用了该链接)。您无法在另一个线程中处理它们,并且由于您没有(正确)处理它们,操作系统会认为您的程序已经崩溃


我做了一个例子来展示一种制作动画的方法。其概念是告诉pygame,在一段时间后,您希望发布一个事件。当该事件出现在事件循环中时,您将执行某些操作

在您的情况下,您告诉pygame在500毫秒后发布
DRAW_TEXT_事件
。当此事件出现在您的事件循环中时,您首先告诉pygame不要再发布
DRAW_TEXT_事件
,而是在1000毫秒后发布
CLEAR_TEXT_事件
。然后你画文本

1000毫秒后,“清除文本”事件将出现在事件循环中。现在你基本上做了同样的事情,但是禁用
清除文本事件
,并告诉pygame在500毫秒后发布
绘制文本事件

我对你的代码没有太大的修改。我在顶部为事件添加了2个定义。我已经删除了你的函数
循环
动画
,并将它们放入游戏循环中。最后,我在
main
函数中添加了游戏循环

import pygame
from pygame.locals import *

# Events that we're going to post.
DRAW_TEXT_EVENT  = pygame.USEREVENT + 1
CLEAR_TEXT_EVENT = pygame.USEREVENT + 2


def encadre(screen):
    pygame.draw.line(screen, (250, 250, 250), (230, 140), (520, 140), 3)
    pygame.draw.line(screen, (250, 250, 250), (230, 190), (520, 190), 3)
    pygame.draw.line(screen, (250, 250, 250), (230, 140), (230, 190), 3)
    pygame.draw.line(screen, (250, 250, 250), (520, 140), (520, 190), 3)


def initRoad(screen):
    pygame.draw.line(screen, (250, 250, 250), (30, 0), (30, 500))
    pygame.draw.line(screen, (250, 250, 250), (100, 0), (100, 500))
    pygame.draw.line(screen, (250, 250, 250), (650, 0), (650, 500))
    pygame.draw.line(screen, (250, 250, 250), (720, 0), (720, 500))
    drawLines(screen)


def drawLines(screen):
    i = 0
    while i <= 49:
        pygame.draw.line(screen, (250, 250, 250), (65, i * 10), (65, (i + 1) * 10))
        pygame.draw.line(screen, (250, 250, 250), (685, i * 10), (685, (i + 1) * 10))
        i = i + 3


def initText(screen, text1):
    text1pos = text1.get_rect()
    text1pos.x = 235
    text1pos.y = 150
    screen.blit(text1, text1pos)

    font1 = pygame.font.Font(None, 30)
    text1 = font1.render("PLAY", 1, (10, 10, 10))
    text1pos = text1.get_rect()
    text1pos.x = 210
    text1pos.y = 310
    screen.blit(text1, text1pos)

    font1 = pygame.font.Font(None, 30)
    text1 = font1.render("QUIT", 1, (10, 10, 10))
    text1pos = text1.get_rect()
    text1pos.x = 490
    text1pos.y = 310
    screen.blit(text1, text1pos)


def animateRoad(screen):  # not done
    pygame.draw.line(screen, (130, 130, 130), (65, 0), (65, 500))
    pygame.draw.line(screen, (130, 130, 130), (685, 0), (685, 500))



def main():
    pygame.init()
    screen = pygame.display.set_mode((750, 500))
    pygame.display.set_caption('Infinite circle run')

    background = pygame.Surface(screen.get_size())
    background = background.convert()
    background.fill((130, 130, 130))
    screen.blit(background, (0, 0))

    encadre(screen)
    initRoad(screen)

    surface1 = pygame.Rect(193, 290, 85, 50)
    button1 = pygame.draw.rect(screen, (0, 0, 240), surface1)
    surface2 = pygame.Rect(472, 290, 85, 50)
    button2 = pygame.draw.rect(screen, (240, 0, 0), surface2)

    font1 = pygame.font.Font(None, 50)
    text1 = font1.render("Infinite circle run", 1, (0, 240, 0))
    initText(screen, text1)

    pygame.display.flip()

    pygame.time.set_timer(DRAW_TEXT_EVENT, 500)

    text1pos = text1.get_rect()

    # GAME LOOP
    while True:

        for event in pygame.event.get():
            if event.type == QUIT:
                return
            elif event.type == pygame.MOUSEBUTTONDOWN:
                if surface1.topleft[0] <= pygame.mouse.get_pos()[0] <= surface1.topright[0]:
                    if surface1.topleft[1] <= pygame.mouse.get_pos()[1] <= surface1.bottomleft[1]:
                        print('play')
                elif surface2.topleft[0] <= pygame.mouse.get_pos()[0] <= surface2.topright[0]:
                    if surface2.topleft[1] <= pygame.mouse.get_pos()[1] <= surface2.bottomleft[1]:
                        return

            elif event.type == DRAW_TEXT_EVENT:
                pygame.draw.rect(screen, (130, 130, 130), (235, 150, 283, 35))
                pygame.time.set_timer(DRAW_TEXT_EVENT,  0)     # Disable the event.
                pygame.time.set_timer(CLEAR_TEXT_EVENT, 1000)  # Post event after 1000ms.
            elif event.type == CLEAR_TEXT_EVENT:
                text1pos.x = 235
                text1pos.y = 150
                screen.blit(text1, text1pos)
                pygame.time.set_timer(CLEAR_TEXT_EVENT, 0)    # Disable the event.
                pygame.time.set_timer(DRAW_TEXT_EVENT,  500)  # Post event after 500ms.

        # Only call once each frame!
        pygame.display.flip()


if __name__ == '__main__':
    main()
导入pygame
从pygame.locals导入*
#我们将要发布的事件。
DRAW\u TEXT\u EVENT=pygame.USEREVENT+1
CLEAR\u TEXT\u EVENT=pygame.USEREVENT+2
def封装(屏幕):
pygame.draw.line(屏幕,(250250250),(230140),(5201440),3)
pygame.draw.line(屏幕,(250250250),(230190),(520190),3)
pygame.draw.line(屏幕,(250250250),(230140),(230190),3)
pygame.draw.line(屏幕,(250250250),(520140),(520190),3)
def初始道路(屏幕):
pygame.draw.line(屏幕,(250250250),(30,0),(30500))
pygame.draw.line(屏幕,(250250250),(100,0),(100500))
pygame.draw.line(屏幕,(250250250),(650,0),(650500))
pygame.draw.line(屏幕,(250250250),(7200),(720500))
抽绳(屏幕)
def抽绳(屏幕):
i=0

而我可能需要像这样初始化线程<代码>线程\u 1=线程(目标=animateTile,args=(屏幕,文本1,),守护进程=True)
我尝试过,但程序仍然会因经典的windows错误“无响应”而崩溃。是的,你是对的,我也不喜欢使用线程,但在这种情况下,我不知道该怎么做,因为我需要标题的动画与鼠标同时运行listener@DariushMohandes就在他们后面画吧。在调用
pygame.display.flip()
之前,您绘制的任何内容都不可见,因此它们将同时显示。@DariushMohandes并确保每帧只调用
pygame.display.flip()
,而不是在每次绘制或blit之后。@DariushMohandes您使用
pygame.time.wait()
会遇到一些麻烦。你不能这样做动画。相反,您可以调用
pygame.time.set_timer()
在一段时间后调用函数()或自己在主循环中计算时间。在我的例子中,我尝试使用函数animatedTitle使标题出现闪烁的错觉,因此我需要使用pygam.display.flip()来实现这一点