我想制作一个开场动画,所以我考虑使用一个主线程来绘制内容,并使用许多小线程来提交绘制请求。
这是因为我想同时绘制多个对象(例如,一个矩形将逐渐绘制,并且一旦达到其绘制的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,然后开始真正的游戏。
您了解我为什么不能在队列中通过地面吗?
如果我只是发送列表中的职位并使用列表,则说明该列表有效。
谢谢