Pyglet 不稳定帧率
我正在尝试用Pyglet创建一个简单的程序,目的是显示动画,并获取一些鼠标输入,然后把这些输入保存到一个文本文件里。不过,我的代码在不使用鼠标的时候,帧率还是很不稳定。
我也看过类似的问题,答案建议使用一个子类化的窗口,或者用schedule_interval
来调用on_draw
这个函数。但是,我不知道怎么用子类化的窗口来显示我的动画,而且当我尝试用schedule_interval
来调用on_draw
时,出现了一个错误,提示on_draw
没有接收到任何参数。
这是我正在使用的代码的一部分:
fps = pyglet.clock.ClockDisplay()# Show FPS
@mywindow.event
def on_mouse_press(x, y, button, modifiers):
global timeStart, file, count
timeNow = time.clock() - timeStart
if button == mouse.LEFT:
print('left click press in {}').format(timeNow)
with open(out_file_name, 'a') as file:
file.write(str(count) +'\t'+ str(timeNow) +'\t'+ '-1\n')
#file.write('' + count + timeNow + 'left click press\n')
count += 1
def update_frames(dt):
global x
x=x+1
@mywindow.event
def on_draw():
pyglet.gl.glClearColor(0,0,0,0)
mywindow.clear()
glColor4f(1,0,0,1)
drawSquare(x,y)#this draws an opengl square
fps.draw()# Show FPS
dt = 1/10.0
pyglet.clock.schedule_interval(update_frames,dt)
pyglet.app.run()
我可以在代码中添加什么来获得一个稳定的帧率呢?
1 个回答
1
我会用这样的方式来做:
import pyglet
from pyglet.gl import *
from collections import OrderedDict
from time import time
from os.path import abspath
class GUI(pyglet.window.Window):
def __init__(self):
super(GUI, self).__init__(640,340, caption='Test')
pyglet.gl.glClearColor(1, 1, 1, 1)
self.alive = True
self.batches = OrderedDict()
self.batches['apples'] = pyglet.graphics.Batch()
self.framerate = 0, time()
self.count = 0
def render(self, *args):
self.clear()
#glColor4f(1,0,0,1)
#drawSquare(x,y)
if time() - self.framerate[1] > 1:
print('fps:',self.framerate[0])
self.framerate = 0, time()
else:
# Not an optimal way to do it, but it will work.
self.framerate = self.framerate[0]+1, self.framerate[1]
self.flip()
def on_draw(self):
self.render()
def on_close(self):
self.alive = False
def on_key_press(self, symbol, modkey):
pass
def on_key_release(self, symbol, modkey):
pass
def on_mouse_release(self, x, y, button, modifiers):
pass
def on_mouse_press(self, x, y, button, modifiers):
self.count += 1
with open('debug.log', 'w') as fh:
fh.write(str(count))
def on_mouse_motion(self, x, y, dx, dy):
pass
def on_mouse_drag(self, x, y, dx, dy, buttons, modifiers):
pass
def run(self):
while self.alive:
event = self.dispatch_events()
if event:
print(event)
self.render()
if __name__ == '__main__':
x = GUI()
pyglet.clock.set_fps_limit(60)
x.run()
首先,这段代码实际上能达到每秒60帧(FPS),这样你对应用程序和主循环的控制会更好。
其次,编码风格可能是个人喜好,但我更喜欢把东西放进类对象里,而不是写一大堆函数,然后把它们附加到比如说@window.update等。这让代码看起来更整洁。
试试看,看看效果如何。
注意:关键在于 event = self.dispatch_events()
这行代码,必须在每次循环中调用,它替代了 app.run()
。
把这些和对象以及渲染结合起来
class House(pyglet.sprite.Sprite):
def __init__(self):
self.texture = pyglet.image.load(abspath('./image.png'))
super(House, self).__init__(self.texture)
self.x = 0
self.y = 0
self.rotation = 0
self.name = 'house'
self.anchor = 'center'
def swap_image(self, image):
self.texture = pyglet.image.load(abspath(image))
self.image = self.texture
def rotate(self, deg):
self.image.anchor_x = self.image.width / 2
self.image.anchor_y = self.image.height / 2
self.rotation = self.rotation+deg
if self.anchor != 'center':
self.image.anchor_x = 0
self.image.anchor_y = 0
return True
def click(self):
print('Clicked:',self.name)
def work(self, *args):
pass
def click_check(self, x, y):
if x > self.x and x < (self.x + self.width):
if y > self.y and y < (self.y + self.height):
return self
def move(self, x, y):
if self.moveable:
self.x += x
self.y += y
def _draw(self):
self.draw()
在 GUI()
中你会这样做:
class GUI(pyglet.window.Window):
def __init__(self):
super(GUI, self).__init__(640,340, caption='Test')
...
self.house = House()
def render(self, *args):
self.house.rotate(1)
self.house._draw()
这应该会创建一个“房子”(或者其他东西),并在每次渲染时旋转1度,这意味着你每秒会旋转60度,效果会很流畅。
这比这更复杂,但这是我通常用来提高FPS同时保持代码可读性的简化版本。因为图形很快就会变得复杂。