For the context, I'm trying to use OpenAI gym together with a pyglet tetris game that I wrote. The problem I'm facing boils down to the MWE below.
After always the same amount of time, here ~9 seconds, the window freezes, but the prints from the toto function AND the render function are still printing. I'm going crazy on this. Pyglet seemed nice but I hardly find any documentation and the official one is hardly helpful. If I do the same with a simpler code with a on_draw() function, no problem, but I need this for the gym part.
Thank you
import pyglet
import time
class Display(pyglet.window.Window):
def __init__(self, ww, wh):
super().__init__(width=ww, height=wh)
class Env:
def __init__(self):
self.window = Display(640, 480)
def render(self, i):
self.window.clear()
label = pyglet.text.Label('iter {:f}'.format(i),
font_size=16,
x=300,
y=200,
anchor_x='left', anchor_y='center')
label.draw()
print('iter {:f}'.format(i))
self.window.flip()
env = Env()
def toto(dt):
for t in range(300):
time.sleep(0.5)
print("toto {:d}".format(t))
env.render(t)
print("done")
pyglet.clock.schedule_once(toto, 1)
pyglet.app.run()
On Windows at least, I wasn't able to reproduce the problem you encountered exactly, but I did notice that the window freezes when it is moved, clicked, minimized/restored. The problem seems to be that you don't dispatch those sorts of events, so they sit it the event queue and prevent further drawing. A quick fix is to call self.window.dispatch_events
after calling self.window.clear()
.
import pyglet
import time
class Display(pyglet.window.Window):
def __init__(self, ww, wh):
super().__init__(width=ww, height=wh)
class Env:
def __init__(self):
self.window = Display(640, 480)
def render(self, i):
self.window.clear()
self.window.dispatch_events()
label = pyglet.text.Label('iter {:f}'.format(i),
font_size=16,
x=300,
y=200,
anchor_x='left', anchor_y='center')
label.draw()
print('iter {:f}'.format(i))
self.window.flip()
env = Env()
def toto(dt):
for t in range(300):
time.sleep(0.5)
print("toto {:d}".format(t))
env.render(t)
print("done")
pyglet.clock.schedule_once(toto, 1)
pyglet.app.run()
You don't seem to be taking much advantage of the default Pyglet event loop here, so you might want to just write your own. Here's one way you could do that.
import pyglet
import time
class Display(pyglet.window.Window):
def __init__(self, ww, wh):
super().__init__(width=ww, height=wh)
self.label = pyglet.text.Label('',
font_size=16,
x=300,
y=200,
anchor_x='left', anchor_y='center')
def on_draw(self):
self.clear()
self.label.draw()
class Env:
def __init__(self):
self.window = Display(640, 480)
def render(self, i):
self.window.label.text = "iter {:f}".format(i)
self.window.switch_to()
self.window.dispatch_events()
self.window.dispatch_event('on_draw')
print('iter {:f}'.format(i))
self.window.flip()
env = Env()
def toto():
for t in range(300):
time.sleep(0.5)
print("toto {:d}".format(t))
env.render(t)
print("done")
toto()