Я пишу небольшое приложение в python 2.7, используя pygame, в котором я хотел бы плавно отображать анимированные фрагменты на экране. Я пишу на Ubuntu, но целевая платформа - это малина Pi, если это актуально. Задача состоит в том, что текстуры для этих анимированных плит хранятся на веб-сервере и должны динамически загружаться с течением времени, а не сразу. Я хотел бы иметь возможность загружать эти изображения в pygame без заметных задержек в моей анимации или ответе на ввод. Частота загрузки довольно низкая, например, захват пары jpg каждые 30 секунд. Я готов долго ждать, пока изображение загрузится в фоновом режиме, если это означает, что основной поток ввода/анимации остается незакрепленным.Загрузка асинхронного изображения в pygame
Таким образом, используя модуль многопроцессорности, я могу асинхронно загружать изображения с сервера в буфер, а затем передавать этот буфер в мой основной процесс pygame через объект multiprocessing.queues.SimpleQueue. Однако, как только буфер доступен в процессе pygame, в моем приложении все еще есть заминка, а буфер загружается в Surface для blitting через pygame.image.frombuffer().
Есть ли способ сделать это pygame.image.load() вызовом асинхронным, чтобы моя анимация в игре и т. Д. Не была заблокирована? Я не могу придумать очевидное решение из-за GIL.
Если бы я писал обычную программу OpenGL в C, я мог бы асинхронно записывать данные на GPU с помощью пиксельного буфера, правильно? Открывает ли pygame любую часть этого API? Кажется, я не могу найти его в документах pygame, которые я довольно новичок, поэтому простите меня, если ответ очевиден. Любая помощь, указывающая, как терминология pygame переводится на OpenGL API, будет большой помощью, а также любые соответствующие примеры, в которых pygame может инициализировать текстуру асинхронно, было бы потрясающе!
Если pygame не предлагает эту функцию, какие у меня варианты? Есть ли способ сделать это с помощью PySDL2?
EDIT: Хорошо, поэтому я попытался использовать pygame.image.frombuffer, и на самом деле он не урезал сцепление, которое я вижу. Любые идеи о том, как я могу сделать это изображение загруженным, действительно асинхронны? Вот некоторые фрагменты кода, иллюстрирующие то, что я сейчас делаю.
Вот код асинхронного у меня есть, что сидит в отдельном процессе от Pygame
def _worker(in_queue, out_queue):
done = False
while not done:
if not in_queue.empty():
obj = in_queue.get()
# if a bool is passed down the queue, set the done flag
if isinstance(obj, bool):
done = obj
else:
url, w, h = obj
# grab jpg at given url. It is compressed so we use PIL to parse it
jpg_encoded_str = urllib2.urlopen(url).read()
# PIL.ImageFile
parser = ImageFile.Parser()
parser.feed(jpg_encoded_str)
pil_image = parser.close()
buff = pil_image.tostring()
# place decompressed buffer into queue for consumption by main thread
out_queue.put((url, w, h, buff))
# and so I create a subprocess that runs _worker function
Вот мой цикл обновления, который работает в основном потоке. Он смотрит, чтобы увидеть, если процесс _Worker поставил что-нибудь в out_queue, и если да, загружает его в Pygame:
def update():
if not out_queue.empty():
url, w, h, buff = img_buffer_queue.get()
# This call is where I get a hitch in my application
image = pygame.image.frombuffer(buff, (w, h), "RGB")
# Place loaded image on the pygame.Sprite, etc in the callback
callback = on_load_callbacks.pop(url, None)
if callback:
callback(image, w, h)
Задумались ли вы о попытке сохранить потоковое изображение в виде пиксельных данных в строке и загрузите это как «Поверхность» через «pygame.image.frombuffer»? http://www.pygame.org/docs/ref/image.html#pygame.image.frombuffer – Haz
Я попробую. Вероятно, это будет быстрее, но не по-настоящему асинхронно. Мне просто нужно делать большие партии и иметь небольшую «загрузку ...», приостанавливая каждый раз, когда я предварительно загружаю пакет. Но это хромало! : D –
@Haz Хорошо, поэтому я попробовал frombuffer() безрезультатно, все еще получая значительное сцепное устройство при загрузке изображений. См. Раздел edit to main post. –