【问题标题】:Pyglet flickers, alternates between two framesPyglet 闪烁,在两帧之间交替
【发布时间】:2022-02-16 00:42:21
【问题描述】:

我正在尝试继承 pyglet.window.Window 以可视化越来越多的随机放置的十字架。不幸的是,Pyglet 似乎不是将这些十字架存储在一个框架中,而是存储在两个不同的交替框架中。大约 50 次迭代后,请查看以下 GIF。

下面是我使用的代码。

import random
import pyglet


class Canvas(pyglet.window.Window):
  def __init__(self, *args, **kwargs):
    super().__init__(*args, **kwargs)
    self.x = 0.
    self.y = 0.

    pyglet.clock.schedule_interval(self.update, .5)

  def update(self, dt: float) -> None:
    if self.has_exit:
      pyglet.app.exit()
    
    self.x = random.random() * self.width
    self.y = random.random() * self.height

  def on_draw(self) -> None:
    pyglet.graphics.draw(2, pyglet.gl.GL_LINES, ('v2f', (self.x - 10, self.y + 10., self.x + 10., self.y - 10.)))
    pyglet.graphics.draw(2, pyglet.gl.GL_LINES, ('v2f', (self.x - 10, self.y - 10., self.x + 10., self.y + 10.)))


def main() -> None:
  canvas = Canvas(width=1024, height=768)
  pyglet.app.run()


if __name__ == '__main__':
  main()

有人可以向我解释发生了什么,甚至可以提供解决方案吗?

编辑:我不想清除帧之间的屏幕。我想在最后一帧的顶部绘制以增加每次调用self.update 时的交叉次数。

【问题讨论】:

    标签: python opengl framebuffer pyglet flicker


    【解决方案1】:

    在您的编辑中:要在前一帧上绘制,请禁用双缓冲区:config = pyglet.gl.Config(double_buffer=False) 并将其传递给窗口初始化。


    绘制前需要清屏,否则之前的帧会一直停留在屏幕上。

      def on_draw(self) -> None:
        self.clear()
        pyglet.graphics.draw(2, pyglet.gl.GL_LINES, ('v2f', (self.x - 10, self.y + 10., self.x + 10., self.y - 10.)))
        pyglet.graphics.draw(2, pyglet.gl.GL_LINES, ('v2f', (self.x - 10, self.y - 10., self.x + 10., self.y + 10.)))
    

    编辑:如果你想增加渲染十字架的数量,你需要增加渲染的东西的数量。这是一个例子:

    
    import random
    import pyglet
    
    class Cross:
        def __init__(self, x, y, batch, size=10):
            self.size = size
            self._position = (x, y)
            self.verts = []
            self.create_vertices(x, y, batch)
    
        @property
        def position(self):
            return self._position
            
        @position.setter
        def position(self, value):
            x, y = value
            self.verts[0].vertices[:] = (x - self.size, y + self.size, x + self.size, y - self.size)
            self.verts[1].vertices[:] = (x - self.size, y - self.size, x + self.size, y + self.size)
            self._position = value
            
        def create_vertices(self, x, y, batch):
            diag1 = batch.add(2, pyglet.gl.GL_LINES, None,
                          ('v2f', (x - self.size, y + self.size, x + self.size, y - self.size)))
                          
            diag2 = batch.add(2, pyglet.gl.GL_LINES, None,
                              ('v2f', (x - self.size, y - self.size, x + self.size, y + self.size)))
                              
            self.verts.append(diag1)
            self.verts.append(diag2)
        
        def delete(self):
            for vert in self.verts:
                vert.delete()
                
            self.verts.clear()
    
    
    class Canvas(pyglet.window.Window):
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
    
            self.crosses = []
    
            self.cross_batch = pyglet.graphics.Batch()
    
            pyglet.clock.schedule_interval(self.update, .5)
            pyglet.clock.schedule_interval(self.create_cross, 1)
    
        def update(self, dt: float) -> None:
            if self.has_exit:
                pyglet.app.exit()
            
            # If you want the stars to move constantly, then uncomment this.
            #for cross in self.crosses:
            #    cross.position = (random.random() * self.width, random.random() * self.height)
    
        def create_cross(self, dt):
            cross = Cross(random.random() * self.width, random.random() * self.height, self.cross_batch, random.randint(3,10))
            self.crosses.append(cross)
    
        def on_draw(self) -> None:
            self.clear()
            self.cross_batch.draw()
            
        def on_key_press(self, symbol, modifiers):
            if symbol == pyglet.window.key.SPACE:
                for cross in self.crosses:
                    cross.delete()
                    
                self.crosses.clear()
    
    
    def main() -> None:
      canvas = Canvas(width=1024, height=768)
      pyglet.app.run()
    
    
    if __name__ == '__main__':
      main()
    

    【讨论】:

    • 非常感谢您的回答!我错过了提到我想避免清除窗口并改为在最后一帧上绘制。我相应地更新了问题。
    • 知道了,在这种情况下,您想禁用双缓冲区:config = pyglet.gl.Config(double_buffer=False) 并将其传递到窗口中。这将允许您在前一个缓冲区的顶部进行绘制,而不会在两者之间闪烁。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-04-09
    • 1970-01-01
    • 1970-01-01
    • 2011-01-19
    • 2017-12-11
    • 2013-03-06
    • 2012-09-03
    相关资源
    最近更新 更多