#python-3.x #pyglet
Вопрос:
Итак, в свободное время я начал писать небольшую игру и решил воспользоваться библиотекой, которой никогда раньше не пользовался: pyglet. Я привык работать с pygame и даже аркадой (которая реализована с помощью pyglet), но подумал, что мне стоит попробовать использовать pyglet хоть раз, особенно потому, что аркада еще не доступна в python 3.10. Итак, фактическая проблема в том, что при создании окна и попытке что-то нарисовать на нем я заметил, что изображение мерцает, поэтому я решил проверить, сколько кадров в секунду я получаю. Следующий код-это просто тест, который я запускал, чтобы попытаться выяснить, что могло произойти.
import pyglet window = pyglet.window.Window(800, 600, vsync=False) fps_display = pyglet.window.FPSDisplay(window) # Redundant just to be sure vsync was indeed disabled window.set_vsync(False) @window.event def on_draw(): window.clear() fps_display.draw() def update(dt): print(f"FPS: {pyglet.clock.get_fps()}") if __name__ == "__main__": pyglet.clock.schedule_interval(update, 1.0/60.0) pyglet.app.run()
Итак, с помощью этого простого кода через FPSDisplay в окне я получаю около 30 кадров в секунду, но из функции печати в методе обновления, которая проверяет часы pyglet, я получаю сотни (или тысячи при перемещении мыши по экрану, что я тоже нахожу странным) кадров в секунду. Я попытался включить и отключить vsync при создании окна и с помощью функции set_vsync, но ничего не изменилось. Единственное, что заставило FPSDisplay (а это была скорость, которую на самом деле рисовали в окне) увеличиться, — это установить частоту обновления функции ниже 1/60 (даже 1/70 уже было достаточно, чтобы получить около 60 кадров в секунду).
pyglet.clock.schedule_interval(update, 1.0/70.0)
Итак, я блуждал, так ли на самом деле работает pyglet или, может быть, проблема с vsync?
Комментарии:
1. 1 — Это происходит даже тогда, когда на экране обновляется информация, например, движущийся спрайт, который заставляет изображение двигаться со скоростью 30 кадров в секунду, а не с желаемыми 60 кадрами в секунду. Приведенный пример был просто тестом, который я проводил. Если pyglet на самом деле работает именно так, как я должен заставить его рисовать материал по крайней мере со скоростью 60 кадров в секунду?
2. 2 — Я, возможно, не был ясен в своем вопросе, за который я извиняюсь, поэтому: почему окно на самом деле будет отображаться с частотой 60 кадров в секунду, просто установив частоту обновления функции обновления на 1/70 вместо 1/60?
3. Я использую экземпляр спрайта pyglet для тестирования. Попытался напрямую добавить значение x в функцию обновления, а затем попытался вызвать базовую функцию обновления, передав увеличивающееся значение x. Они оба приводят к одинаковым 30 кадрам в секунду. Как я заметил ошибку, я не пытался использовать key_press или что-либо еще.
4. Подумал, что это тоже было что-то из этих строк, и экспериментировал с этим. С 61,0 до 64,0 он колеблется в пределах 40-50; с 65,0 до 67,0 он остается на уровне ниже 50-х годов; с 68 до 60-х годов он достигает и остается довольно стабильным. Без перемещения мыши или нажатия чего-либо, даже с 120,0, это дает мне те же 60 кадров в секунду, но при перемещении мыши она увеличивается примерно до 120 кадров в секунду. Я действительно не понимаю, почему это происходит
Ответ №1:
Как правило, вы не хотите, чтобы игра работала с максимальной частотой кадров в секунду без особых усилий, иначе вы перегружаете карту и без причины тратите циклы процессора.
В основном цикл событий пытается оптимизировать это для вас. Чтобы ответить на вопрос, почему, Pyglet обновит FPS только в том случае, если произойдет какое-либо событие. (Это изменяется в Pyglet 2.0, так как это не совсем интуитивно понятно) Вы можете увидеть это, перемещая курсор мыши вокруг и наблюдая, как увеличивается частота кадров в секунду. Windows помещает события в окно, заставляя приложение работать больше. Планируя обновление, вы заставляете цикл работать больше, поэтому он увеличивается.
Если вы хотите увеличить максимальную частоту кадров в секунду даже с помощью vsync, вы можете просто сделать:
def update(dt): pass pyglet.clock.schedule(update)
Как правило, как только вы начнете добавлять более сложные функции и функции, это не должно быть проблемой.
Комментарии:
1. Хорошо, теперь это определенно имеет больше смысла. Спасибо за ответ