带有线程的pygame绘图,在尝试弯曲表面时显示Surface退出

时间:2019-04-30 06:00:57

标签: python python-2.7 pygame pygame-surface

我想制作一个开场动画,所以我考虑使用一个主线程来绘制内容,并使用许多小线程来提交绘制请求。

这是因为我想同时绘制多个对象(例如,一个矩形将逐渐绘制,并且一旦达到其绘制的50%,我想开始绘制其他内容,此处未做,这只是一个测试)

所以我正在做一个测试,并且工作正常,但是当我尝试对表面进行blit时,出现了这个异常:

Traceback (most recent call last):
  File "C:\Python27\lib\threading.py", line 801, in __bootstrap_inner
    self.run()
  File "C:\Python27\lib\threading.py", line 754, in run
    self.__target(*self.__args, **self.__kwargs)
  File "C:\checkouts\anim_project\test.py", line 74, in opening_animation_drawer_thread
    drawing_task.draw_yourself(main_window_surface)
  File "C:\checkouts\anim_project\test.py", line 31, in draw_yourself
    main_window_surface.blit(self.surfaces[self.pos_in_list], self.pos_in_screen)
error: display Surface quit

这是程序,要运行该程序,您需要一个带有几个png / jpg的“球”文件夹,这是一个Google链接,其中包含包含所有内容的存档:https://drive.google.com/open?id=1dW1_kf4trEvH0j_A-1wQ4fW3olK1_7mP

这是代码:

#!/usr/bin/env python
#-*- coding: utf-8 -*-

import time
import pygame
import os

from threading import Thread
from pygame.locals import *
from multiprocessing import Queue
from os import listdir
from os.path import isfile, join

class DrawingTaskLine():
    def __init__(self, start, end, color, thickness):
        self.start = start
        self.end = end
        self.color = color
        self.thickness = thickness

    def draw_yourself(self, main_window_surface):
        pygame.draw.line(main_window_surface, self.color, self.start, self.end,  self.thickness)

class DrawingTaskImage():
    def __init__(self, surfaces, pos_in_list, pos_in_screen):
        self.surfaces = surfaces
        self.pos_in_list = pos_in_list
        self.pos_in_screen = pos_in_screen

    def draw_yourself(self, main_window_surface):
        main_window_surface.blit(self.surfaces[self.pos_in_list], self.pos_in_screen)

def get_all_files_from(my_path):
    file_list_without_path = [f for f in listdir(my_path) if
                              isfile(join(my_path, f)) and 'desktop.ini' not in f]
    return file_list_without_path

def load_all_images_from(my_path, resize_hw=None):
    res = []
    for im_name in get_all_files_from(my_path):
        im_surface = pygame.image.load(os.path.abspath(join(my_path, im_name)))
        if resize_hw is not None:
            im_surface = pygame.transform.scale(im_surface, resize_hw)
        res.append(im_surface)
    return res

commonQueue = Queue()
openingAnimationisRunning = True

main_window_im_width = 900
main_window_im_height = 750
pygame.init()
window = pygame.display.set_mode((main_window_im_width, main_window_im_height))

#making main window
background_color = (50 , 50, 50)
origin_position = (0, 0)
main_window_surface = pygame.Surface((main_window_im_width, main_window_im_height))
main_window_surface.fill(background_color)
window.blit(main_window_surface, origin_position)

print "Loading images....."
ball_size_hw = 100, 100
ball_surfaces = load_all_images_from("ball", ball_size_hw)
print "Loading completed!"

def opening_animation_drawer_thread():
    while openingAnimationisRunning:
        drawing_task = commonQueue.get()

        if drawing_task is None:
            continue

        drawing_task.draw_yourself(main_window_surface)
        window.blit(main_window_surface, origin_position)

def draw_horizonral_lines_animation():
    y = 0
    color_counter = 0
    x_left = 50
    x_right = 300
    colors = [(255,0,0), (0,255,0), (0,0,255)]
    thickness = 1
    while True:
        x1 = (x_left, y)
        x2 = (x_right, y)
        drawing_task = DrawingTaskLine(x1, x2, colors[color_counter], thickness)
        commonQueue.put(drawing_task)
        y += 1
        if (y == main_window_im_height):
            y = 0
            color_counter += 1
        if (color_counter == 3):
            color_counter = 0

def draw_vertical_lines_animation():
    x_start = 350
    x = x_start
    color_counter = 0
    y_top= 400
    y_bottom = 500
    colors = [(255,0,0), (0,255,0), (0,0,255)]
    thickness = 1
    while True:
        y1 = (x, y_top)
        y2 = (x, y_bottom)
        drawing_task = DrawingTaskLine(y1, y2, colors[color_counter], thickness)
        commonQueue.put(drawing_task)
        x += 1
        if (x == main_window_im_width-50):
            x = x_start
            color_counter += 1
        if (color_counter == 3):
            color_counter = 0


def draw_ball_animation():
    time.sleep(5)
    ball_pos = 540, 140
    for n in range(len(ball_surfaces)):
        commonQueue.put(DrawingTaskImage(ball_surfaces, n, ball_pos))
        time.sleep(0.01)


def launch_threaded_animation():
    main_drawer_thread = Thread(target=opening_animation_drawer_thread)
    main_drawer_thread.start()

    draw_horizonral_lines_animation_thread = Thread(target=draw_horizonral_lines_animation)
    draw_horizonral_lines_animation_thread.start()

    draw_vertical_lines_animation_thread = Thread(target=draw_vertical_lines_animation)
    draw_vertical_lines_animation_thread.start()

    draw_ball_animation_thread = Thread(target=draw_ball_animation)
    draw_ball_animation_thread.start()


launch_threaded_animation()
do = True
while do:
    for event in pygame.event.get():
        if event.type == QUIT:
            do = False

    # do your stuff here once all thread have finished
    pygame.display.flip()

想法是,一旦所有动画完成,它们就会将布尔值设为True,然后开始真正的游戏。

您了解我为什么不能在队列中通过地面吗?

如果我只是发送列表中的职位并使用列表,则说明该列表有效。

谢谢

0 个答案:

没有答案