【问题标题】:FPS with Pyglet half of monitor refresh rate具有 Pyglet 一半显示器刷新率的 FPS
【发布时间】:2013-02-07 02:06:14
【问题描述】:

我是 Pyglet 的新手,我编写了一个小程序,可以在屏幕上移动一个球。现在我很难建立 60 fps 的稳定帧速率。虽然 Pyglet 应该与我的显示器的 60Hz 刷新率同步,但 Pyglet 将我的 fps 设置为我的刷新率的一半(例如,当 60Hz、30 fps 时)。我的代码中是否有问题导致此问题?

import pyglet
import physicalobject
import random
from pyglet.window import mouse

pyglet.resource.path = ['./resources']
pyglet.resource.reindex()

ball_image = pyglet.resource.image("ball2.png")

#sets clock format
fps_display = pyglet.clock.ClockDisplay(format='%(fps).2f fps')

def center_image(image):
    image.anchor_x = image.width/2
    image.anchor_y = image.height/2

center_image(ball_image)
ball = physicalobject.PhysicalObject(img=ball_image, x = 400, y = 300)
ball.scale = .2
ball.velocity_x = random.randint(-4,4)*150
ball.velocity_y = random.randint(-4,4)*150

#Calls update function to set new ball position based on velocity
def update(dt):
     ball.update(dt)

@window.event
def on_mouse_drag(x, y, dx, dy, button, modifiers):
     ball.x = x
     ball.y = y
     ball.velocity_x = dx * 20
     ball.velocity_y = dy * 20

@window.event
def on_draw():
     window.clear()
     ball.draw()
     fps_display.draw()

def main():
     pyglet.clock.schedule_interval(update, 1/120.0)
     pyglet.app.run()

if __name__ == '__main__':
     main()

【问题讨论】:

  • 如果您使用pyglet.clock.schedule(update) 而不是schedule_interval,您是否看到了改进?
  • 好像没什么区别。
  • 在提出问题时,您运行的是什么版本的 Pyglet,因为 1.1.1 在帧率方面存在一些问题。

标签: python pyglet


【解决方案1】:

Pyglet 在某些系统上根本无法正确处理它,您必须禁用应用程序窗口的 vsync 才能使其工作。下面是一个示例脚本,您可以运行它来了解它的工作原理:

import pyglet

# Show FPS
fps = pyglet.clock.ClockDisplay()

# The game window
class Window(pyglet.window.Window):
    def __init__(self):
        super(Window, self).__init__(vsync = False)
        # Run "self.update" 128 frames a second and set FPS limit to 128.
        pyglet.clock.schedule_interval(self.update, 1.0/128.0)
        pyglet.clock.set_fps_limit(128)

    # You need the dt argument there to prevent errors,
    # it does nothing as far as I know.
    def update(self, dt): 
        pass

    def on_draw(self):
        pyglet.clock.tick() # Make sure you tick the clock!
        self.clear()
        fps.draw()

# Create a window and run
win = Window()
pyglet.app.run()

【讨论】:

  • 这行得通,几乎……除了你不能使用时钟……它有局限性。
  • 所以 vsync 部分是真的,如果你设置vsync = True 那么应用程序将被强制锁定到显示器刷新率,这是为了减少如果应用程序在这样的情况下刷新可能发生的屏幕撕裂眼睛可以捕捉到差异的同步方式..这意味着它会显得不同步或滞后,而实际上它只是您的屏幕渲染速度如此之快,并且在显示器刷新时会发生更新,因此屏幕撕裂。但是时钟不会显示正确的刷新率,它只会给您一种刷新率显示的错觉:)
  • @Torxed 有什么限制?我的印象是时钟应该用于安排活动。
【解决方案2】:
import pyglet
from time import time, sleep

class Window(pyglet.window.Window):
    def __init__(self, refreshrate):
        super(Window, self).__init__(vsync = False)
        self.frames = 0
        self.framerate = pyglet.text.Label(text='Unknown', font_name='Verdana', font_size=8, x=10, y=10, color=(255,255,255,255))
        self.last = time()
        self.alive = 1
        self.refreshrate = refreshrate

    def on_draw(self):
        self.render()

    def render(self):
        self.clear()
        if time() - self.last >= 1:
            self.framerate.text = str(self.frames)
            self.frames = 0
            self.last = time()
        else:
            self.frames += 1
        self.framerate.draw()
        self.flip()

    def on_close(self):
        self.alive = 0

    def run(self):
        while self.alive:
            self.render()
            event = self.dispatch_events()
            sleep(1.0/self.refreshrate)

win = Window(23) # set the fps
win.run()

请注意缺少时钟功能。 另外,尝试设置vsync = True 并删除sleep(1.0/self.refreshrate),这将锁定显示器的刷新率。

另外,请注意我不使用pyglet.app.run() 来锁定渲染过程,而是调用self.dispatch_events()。它实际上并没有做任何事情,除了让图形“轮询”并继续前进,没有它。 .pyglet 等待轮询发生,pyglet.app.run() 通常会这样做。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-09-01
    • 1970-01-01
    • 2011-12-18
    • 2020-08-16
    • 2012-08-05
    • 2012-07-06
    • 1970-01-01
    • 2022-06-11
    相关资源
    最近更新 更多