2014-02-10 3 views
2

Я пишу небольшое приложение в 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) 
+0

Задумались ли вы о попытке сохранить потоковое изображение в виде пиксельных данных в строке и загрузите это как «Поверхность» через «pygame.image.frombuffer»? http://www.pygame.org/docs/ref/image.html#pygame.image.frombuffer – Haz

+0

Я попробую. Вероятно, это будет быстрее, но не по-настоящему асинхронно. Мне просто нужно делать большие партии и иметь небольшую «загрузку ...», приостанавливая каждый раз, когда я предварительно загружаю пакет. Но это хромало! : D –

+0

@Haz Хорошо, поэтому я попробовал frombuffer() безрезультатно, все еще получая значительное сцепное устройство при загрузке изображений. См. Раздел edit to main post. –

ответ

0

Может быть, вы могли бы попытаться преобразовать изображение из объекта буфера для более эффективного объекта в функции работника , возможно, поверхность, а затем отправить эту вычисленную поверхность в очередь ожидания? Таким образом, генерация поверхностного объекта не будет блокировать основной поток.

+0

Это, к сожалению, не сработает, потому что pygame может создавать только поверхности в главном обработать. Я мог бы сделать поверхность в отдельном потоке, но это все еще создает заикание в моей основной теме из-за GIL. –

Смежные вопросы