I am trying to subclass pyglet.window.Window
to visualize an increasing number of randomly placed crosses. Unfortunately, Pyglet seems to store those crosses, not in one, but in two different, alternating frames. See the following GIF after about 50 iterations.
Below is the code I used.
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()
Could someone explain to me what's going on and maybe even provide a solution?
Edit: I don't want to clear the screen between frames. I want to draw on top of the last frame to increase the number of crosses with every call of self.update
.
On your edit: To draw on the previous frame, disable the double buffer: config = pyglet.gl.Config(double_buffer=False) and pass that into the Window initialization.
You need to clear the screen before you draw, otherwise the previous frames will stay on the screen.
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.)))
EDIT: If you want to increase the amount of rendered crosses, you will need to increase the amount of things rendered. Here is an example:
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()