def main(): # Create the main window window = Window(800, 600, visible=False, caption="FF:Tactics.py", style='dialog') # Create the default camera and have it always updating camera = Camera((-600, -300, 1400, 600), (400, 300), 300, speed=PEPPY) clock.schedule(camera.update) # Load the first scene world = World(window, camera) world.transition(MainMenuScene) # centre the window on whichever screen it is currently on window.set_location(window.screen.width/2 - window.width/2, window.screen.height/2 - window.height/2) # clear and flip the window # otherwise we see junk in the buffer before the first frame window.clear() window.flip() # make the window visible at last window.set_visible(True) # finally, run the application pyglet.app.run()
def main(): # Create the main window window = Window(800, 600, visible=False, caption="FF:Tactics.py", style='dialog') # Create the default camera and have it always updating camera = Camera((-600, -300, 1400, 600), (400, 300), 300, speed=PEPPY) clock.schedule(camera.update) # Load the first scene world = World(window, camera) world.transition(MainMenuScene) # centre the window on whichever screen it is currently on window.set_location(window.screen.width / 2 - window.width / 2, window.screen.height / 2 - window.height / 2) # clear and flip the window # otherwise we see junk in the buffer before the first frame window.clear() window.flip() # make the window visible at last window.set_visible(True) # finally, run the application pyglet.app.run()
class Egg(object): def __init__(self, width, height): # display initializations self.__window = Window(width, height, vsync=True) self.__background_color = (0, 0, 0, 1.0) # self._fps_display = pyglet.clock.ClockDisplay() self.__key_state_handler = key.KeyStateHandler() self.__scene = None self.__window.event(self.on_draw) self.__window.push_handlers(self.__key_state_handler) self.__camera = None #schedule regular updates pyglet.clock.schedule_interval(self.update, 1 / 100.0) @property def window(self): return self.__window @property def background_color(self): return self.__background_color @background_color.setter def background_color(self, value): self.__background_color = value def register_scene(self, scene): self.__scene = scene self.__camera = Camera("main_camera", (0, 0), self.__window.height / 2.) self.__scene.root.add_child(self.__camera) self.__camera.target.x = self.__window.width / 2. self.__camera.target.y = self.__window.height / 2. self.__window.event(self.__scene.on_mouse_press) self.__window.event(self.__scene.on_mouse_release) self.__window.event(self.__scene.on_mouse_drag) self.__window.event(self.__scene.on_mouse_motion) def on_draw(self): self.__window.clear() glClearColor(*self.__background_color) if self.__scene is not None: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) # draw batches self.__camera.focus(self.__window.width, self.__window.height) self.__scene.draw() # draw specific batches for the hud self.__camera.hud_mode(self.__window.width, self.__window.height) self.__scene.draw_head_display() def update(self, dt): if self.__scene is not None: self.__scene.update(dt) self.__scene.process_keyboard(self.__key_state_handler, dt) self.__camera.update(dt)
class Egg(object): def __init__(self, width, height): # display initializations self.__window = Window(width, height, vsync=True) self.__background_color = (0, 0, 0, 1.0) # self._fps_display = pyglet.clock.ClockDisplay() self.__key_state_handler = key.KeyStateHandler() self.__scene = None self.__window.event(self.on_draw) self.__window.push_handlers(self.__key_state_handler) self.__camera = None #schedule regular updates pyglet.clock.schedule_interval(self.update, 1 / 100.0) @property def window(self): return self.__window @property def background_color(self): return self.__background_color @background_color.setter def background_color(self, value): self.__background_color = value def register_scene(self, scene): self.__scene = scene self.__camera = Camera("main_camera", (0, 0), self.__window.height / 2.) self.__scene.root.add_child(self.__camera) self.__camera.target.x = self.__window.width / 2. self.__camera.target.y = self.__window.height / 2. self.__window.event(self.__scene.on_mouse_press) self.__window.event(self.__scene.on_mouse_release) self.__window.event(self.__scene.on_mouse_drag) self.__window.event(self.__scene.on_mouse_motion) def on_draw(self): self.__window.clear() glClearColor(*self.__background_color) if self.__scene is not None: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) # draw batches self.__camera.focus(self.__window.width, self.__window.height) self.__scene.draw() # draw specific batches for the hud self.__camera.hud_mode(self.__window.width, self.__window.height) self.__scene.draw_head_display() def update(self, dt): if self.__scene is not None: self.__scene.update(dt) self.__scene.process_keyboard(self.__key_state_handler, dt) self.__camera.update(dt)
class MainWindow: def __init__(self, fullscreen): self.fullscreen = fullscreen self.config = Config() self.Instance = vlc.Instance() self.player = self.Instance.media_player_new() media = self.Instance.media_new(self.config.configs['playlist'][1]) self.player.set_media(media) #self.player = media.Player() #track = media.load(self.config.configs['playlist'][1]) #self.player.queue(track) self.texts = ['Movies', 'TV', 'Music', 'Options'] self.index = 0 self.maxIndex = 3 self.mainWindow = Window(fullscreen=self.fullscreen) self.label = Label(self.config.ui['greeting'], font_name='Monospace', font_size=24, x=self.mainWindow.width // 2, y=self.mainWindow.height // 2, anchor_x='center', anchor_y='center') @self.mainWindow.event def on_draw(): self.mainWindow.clear() self.label.draw() # if self.player.get_texture(): # self.player.get_texture().blit(0, 0) @self.mainWindow.event def on_key_press(symbol, modifiers): if symbol == key.UP: if self.index == self.maxIndex: self.index = 0 else: self.index += 1 elif symbol == key.DOWN: if self.index == 0: self.index = self.maxIndex else: self.index -= 1 elif symbol == key.SPACE: #self.player = vlc.MediaPlayer(self.config.configs['playlist'][1]) #self.player.play() self.player.set_xwindow(self.GetHandle()) self.player.play() elif symbol == key.RETURN: self.player.pause() self.label.text = self.texts[self.index] def Run(self): app.run()
class Gameloop(object): def __init__(self): self.window = None def init(self): self.world = World() self.world.init() populate(self.world) bitmaps = Bitmaps() bitmaps.load() self.render = Render(bitmaps) self.camera = Camera(zoom=10.0) self.window = Window(fullscreen=False, visible=False) self.window.set_exclusive_mouse(True) self.window.on_draw = self.draw self.window.on_resize = self.render.resize self.controls = Controls(self.world.bat) self.window.set_handlers(self.controls) self.render.init() clock.schedule(self.update) self.hud_fps = clock.ClockDisplay() self.window.set_visible() def update(self, dt): # scale dt such that the 'standard' framerate of 60fps gives dt=1.0 dt *= 60.0 # don't attempt to compensate for framerate of less than 30fps. This # guards against huge explosion when game is paused for any reason # and then restarted dt = min(dt, 2) self.controls.update() self.world.update() self.window.invalid = True def draw(self): self.window.clear() self.camera.world_projection(self.window.width, self.window.height) self.camera.look_at() self.render.draw(self.world) self.hud_fps.draw() return EVENT_HANDLED def stop(self): if self.window: self.window.close()
class Gameloop(object): def __init__(self): self.camera = None self.projection = None self.render = None self.window = None self.world = None self.fpss = [] def prepare(self, options): self.window = Window(fullscreen=options.fullscreen, vsync=False, visible=False, resizable=True) self.window.on_draw = self.draw self.projection = Projection(self.window.width, self.window.height) self.window.on_resize = self.projection.resize self.world = World() self.camera = Camera() self.world.add(GameItem(camera=self.camera, position=Origin, move=WobblyOrbit(32, 1, speed=-0.5))) self.render = Render(self.world) self.render.init() pyglet.clock.schedule(self.update) self.clock_display = pyglet.clock.ClockDisplay() vs = VertexShader(join("flyinghigh", "shaders", "lighting.vert")) fs = FragmentShader(join("flyinghigh", "shaders", "lighting.frag")) shader = ShaderProgram(vs, fs) shader.use() def update(self, dt): # self.fpss.append(1/max(1e-3, dt)) dt = min(dt, 1 / 30) self.world.update(dt) self.window.invalid = True def draw(self): self.window.clear() self.projection.set_perspective(45) self.camera.look_at(Origin) self.render.draw() self.projection.set_screen() self.camera.reset() self.render.draw_hud(self.clock_display) return EVENT_HANDLED def stop(self): if self.window: self.window.close()
class Game(): def __init__(self): gl.glEnable(gl.GL_TEXTURE_2D) gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST) gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA) self.window = Window(width=640, height=360, resizable=True) self.window.config.alpha_size = 8 gl.glEnable(gl.GL_BLEND) self.window.set_caption('KeysManiac (development build)') Grid.set_factor_from_resolution(*self.window.get_size()) self.window.push_handlers(self) self.scene = None def load_scene(self, scene_class): context = None if self.scene: context = self.scene.context self.scene.unload() new_scene = scene_class(game=self, context=context) new_scene.load() self.scene = new_scene def on_draw(self): if not self.scene: logging.warning('No scene has been loaded') return self.window.clear() self.scene.draw() def on_resize(self, width, height): Grid.set_factor_from_resolution(width, height) if not self.scene: return self.scene.resize() def on_activate(self): self.on_draw() def on_key_press(self, symbol, modifiers): if not self.scene: return self.scene.on_key_press(symbol, modifiers) def on_key_release(self, symbol, modifiers): if not self.scene: return self.scene.on_key_release(symbol, modifiers)
class ImageViewer: def __init__(self, display=None, maxwidth=500): self.window = None self.isopen = False self.display = display def __del__(self): self.close() def imshow(self, arr, caption): if self.window is None: height, width, _ = arr.shape self.window = Window(width=width, height=height, display=self.display, vsync=False, resizable=True) self.width = width self.height = height self.isopen = True assert len(arr.shape) == 3 height, width, _ = arr.shape image = pyglet.image.ImageData(width, height, 'RGB', arr.tobytes(), pitch=-3 * width) gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST) texture = image.get_texture() texture.width = self.width texture.height = self.height self.window.clear() self.window.switch_to() self.window.dispatch_events() texture.blit(0, 0) self.window.flip() self.window.set_caption(caption) def close(self): if self.isopen: self.window.close() self.isopen = False
class NumpyTube: def __init__(self): self.window = None self.isopen = False def __del__(self): self.close() def imshow(self, img, caption=None): height, width, _ = img.shape pitch = -3 * width if self.window is None: self.window = Window(width=width, height=height, vsync=False) self.width = width self.height = height self.isopen = True data = img.tobytes() image = pyglet.image.ImageData(width, height, "RGB", data, pitch=pitch) gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST) texture = image.get_texture() texture.width = self.width texture.height = self.height self.window.clear() self.window.switch_to() self.window.dispatch_events() texture.blit(0, 0) self.window.flip() if caption is not None: self.window.set_caption(caption) def close(self): if self.isopen: self.window.close() self.window = None self.isopen = False
class ImageViewer(object): """A simple class for viewing images using pyglet.""" def __init__(self, caption, height, width): """ Initialize a new image viewer. Args: caption (str): the caption/title for the window height (int): the height of the window width (int): the width of the window Returns: None """ self.caption = caption self.height = height self.width = width self._window = None def __repr__(self): """Return an executable string representing this object.""" template = '{}(caption={}, height={}, width={})' return template.format(self.caption, self.height, self.width) def __del__(self): """Close any open windows and delete this object.""" self.close() @property def is_open(self): """Return a boolean determining if this window is open.""" return self._window is not None def open(self): """Open the window.""" self._window = Window( caption=self.caption, height=self.height, width=self.width, vsync=False, resizable=True, ) def show(self, frame): """ Show an array of pixels on the window. Args: frame (numpy.ndarray): the frame to show on the window Returns: None """ # check that the frame has the correct dimensions if len(frame.shape) != 3: raise ValueError('frame should have shape with only 3 dimensions') # open the window if it isn't open already if not self.is_open: self.open() # prepare the window for the next frame self._window.clear() self._window.switch_to() self._window.dispatch_events() # create an image data object image = ImageData(frame.shape[1], frame.shape[0], 'RGB', frame.tobytes(), pitch=frame.shape[1] * -3) # send the image to the window image.blit(0, 0, width=self._window.width, height=self._window.height) self._window.flip() def close(self): """Close the window.""" if self.is_open: self._window.close() self._window = None
class Client( object ): def __init__(self, app): self.app = app self.window = Window( width=self.app.size[0], height=self.app.size[1], style='dialog', resizable=False ) self.window.set_caption("ASTAR MAZE") self.window.on_close = sys.exit self.ctrl = InputHandler(self) self.window.push_handlers(self.ctrl) self.clock = Clock() self.clock.set_fps_limit(30) self.window.push_handlers(self.clock) self.grid = ClientGrid( self.app.grid ) # S q u a r e s self.entities = {} self.setup() def setup(self): glClearColor( .113, .121, .1289, 1 ) glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ) glDisable( GL_LIGHTING ) glCullFace( GL_BACK ) glDisable( GL_DEPTH_TEST ) self.runner = None self.goal = None self.isSearching = False self.found = False self.solution = [] self.prev = None self.entitiesBatch = pyglet.graphics.Batch() group = ClientGroup() for k,v in self.app.squares.iteritems(): verts = self.entitiesBatch.add( 4, GL_QUADS, group, 'v2i/static', 'c4B/dynamic' ) verts.vertices = v.vertices['positions'] verts.colors = v.vertices['colors'] self.entities[k] = ClientSquare( v, verts ) def draw(self): self.grid.draw() self.entitiesBatch.draw() if self.found: curr = None if self.prev: self.setVisited( self.entities[self.prev] ) if len(self.solution): curr = self.solution.pop() self.entities[curr].update( SquareType.RUNNER ) self.prev = curr def update(self): self.clock.tick() self.window.dispatch_events() self.window.clear() self.draw() self.window.flip() def reset(self): self.app.setup() self.setup() def astar(self): startState = ASState( self.runner.pos, self.goal.pos, self ) nodesGenerated = 1 frontier = Heap() expanded = set() frontier.push( 0, ASNode( startState ) ) while len(frontier): n = frontier.pop() if n.state.isGoal(): self.solution = n.execute() print "%d node(s) generated.\n" % nodesGenerated return True successors = n.state.expand() for succ in successors: if succ['successor'] not in expanded: nodesGenerated = nodesGenerated + 1 nprime = ASNode( succ['successor'], succ['action'], n ) frontier.push( nprime.hCost, nprime ) expanded.add( succ['successor'] ) return False def search(self): if not self.runner or not self.goal: print "You must select a start and end position on the grid" print "Press 1 and then click a square for start position (in purple)." print "Press 2 and then click a square for end position (in red)." else: self.isSearching = True print "\nRUNNING A*\n" print "Goal position: \t", self.goal.pos print "Start position: \t", self.runner.pos print "Using heuristic: \t%s\n" % SETTINGS['HEURISTIC'] if self.astar(): self.found = True else: print "Failed to solve maze." self.isSearching = False def pressSquare( self, sqr ): sqr.update( SquareType.BLOCKED ) def resetSquare( self, sqr ): sqr.update( SquareType.EMPTY ) def setStart( self, sqr ): if not self.runner: sqr.update( SquareType.START ) self.runner = sqr def setEnd( self, sqr ): if not self.goal: sqr.update( SquareType.GOAL ) self.goal = sqr def setVisited( self, sqr ): sqr.update( SquareType.TRAIL )
class EventLoopFixture(InteractiveFixture): question = '\n\n(P)ass/(F)ail/(S)kip/(Q)uit?' key_pass = key.P key_fail = key.F key_skip = key.S key_quit = key.Q clear_color = 1, 1, 1, 1 base_options = { 'width': 300, 'height': 300, } def __init__(self, request): super().__init__(request) self._request = request self.window = None self.text_batch = None self.text_document = None self.answer = None request.addfinalizer(self.tear_down) def tear_down(self): if self.window: self.window.close() self.window = None def create_window(self, **kwargs): combined_kwargs = {} combined_kwargs.update(self.base_options) combined_kwargs.update(kwargs) self.window = Window(**combined_kwargs) self.window.push_handlers(self) return self.window def get_document(self): if self.text_document is None: self._create_text() return self.text_document def _create_text(self): assert self.window is not None self.text_batch = Batch() self.text_document = FormattedDocument() layout = TextLayout(self.text_document, self.window.width, self.window.height, multiline=True, wrap_lines=True, batch=self.text_batch) layout.content_valign = 'bottom' def add_text(self, text): self.get_document() self.text_document.insert_text(len(self.text_document.text), text) def ask_question(self, description=None, screenshot=True): """Ask a question inside the test window. By default takes a screenshot and validates that too.""" if self.window is None: self.create_window() self.add_text('\n\n') if description: self.add_text(description) self.add_text(self.question) self.answer = None caught_exception = None try: if self.interactive: self.run_event_loop() self.handle_answer() else: self.run_event_loop(0.1) except Exception as ex: import traceback traceback.print_exc() caught_exception = ex finally: if screenshot: try: screenshot_name = self._take_screenshot(self.window) if caught_exception is None and not self.interactive: self._check_screenshot(screenshot_name) except: if not caught_exception: raise if caught_exception: raise caught_exception def handle_answer(self): if self.answer is None: raise Exception('Did not receive valid input in question window') elif self.answer == self.key_fail: # TODO: Ask input pytest.fail('Tester marked test failed') elif self.answer == self.key_skip: pytest.skip('Tester marked test skipped') elif self.answer == self.key_quit: pytest.exit('Tester requested to quit') def ask_question_no_window(self, description=None): """Ask a question to verify the current test result. Uses the console or an external gui as no window is available.""" super().ask_question(description) def run_event_loop(self, duration=None): if duration: clock.schedule_once(self.interrupt_event_loop, duration) pyglet.app.run() def interrupt_event_loop(self, *args, **kwargs): pyglet.app.exit() @staticmethod def schedule_once(callback, dt=.1): clock.schedule_once(callback, dt) def on_draw(self): self.clear() self.draw_text() def clear(self): gl.glClearColor(*self.clear_color) self.window.clear() def draw_text(self): if self.text_batch is not None: self.text_batch.draw() def on_key_press(self, symbol, modifiers): if symbol in (self.key_pass, self.key_fail, self.key_skip, self.key_quit): self.answer = symbol self.interrupt_event_loop() # Prevent handling of Escape to close the window return True
class Game(): def __init__(self): self.batch = Batch() self.background = Rectangle(0, 0, 0, 0) self.window = Window() self.window.push_handlers(self) self.on_resize(self.window.width, self.window.height) clock.schedule_interval(self.update, 1 / 60) clock.schedule_interval(self.log, 1) self.sounds = { 'fail': media.load('resources/failure.mp3', streaming=False), 'jump': media.load('resources/jump.wav', streaming=False), 'score': media.load('resources/score.wav', streaming=False), } self.reset() def log(self, delta): logging.info('Current speed: {}'.format(self.speed)) logging.info('Current score: {}'.format(self.points)) def reset(self): self.pipes = [] self.points = 0 self.speed = 2 self.player = Player(batch=self.batch) self.create_pipe() self.create_pipe(x=(Grid.columns / 2) + (Pipe.WIDTH / 2)) def fail(self): self.sounds['fail'].play() self.reset() def create_pipe(self, *args, **kwargs): kwargs['batch'] = kwargs.get('batch', self.batch) self.pipes.append(Pipe(*args, **kwargs)) def update(self, delta): self.player.update(delta) self.speed += delta * 0.1 delta_x = delta * Grid.x() * self.speed if self.player.is_offscreen(): self.fail() return for pipe in self.pipes: pipe.scroll(delta_x) if pipe.is_offscreen(): self.pipes.remove(pipe) self.create_pipe() if pipe.collides(self.player.center): self.fail() if self.player.cleared(pipe): self.score() def score(self): self.sounds['score'].play() self.points += 1 def jump(self): logging.info('jumping') self.sounds['jump'].play() self.player.jump() def on_key_press(self, symbol, modifiers): self.jump() def on_mouse_press(self, x, y, button, modifiers): self.jump() def on_draw(self): self.window.clear() self.background.draw() self.batch.draw() def on_resize(self, width, height): Grid.update_factor(width, height) self.background.width, self.background.height = width, height if getattr(self, 'player', None): self.player.resize()
class Gameloop(object): def __init__(self): self.camera = None self.projection = None self.render = None self.window = None self.world = None self.fpss = [] def prepare(self, options): self.window = Window( fullscreen=options.fullscreen, vsync=False, visible=False, resizable=True) self.window.on_draw = self.draw self.projection = Projection(self.window.width, self.window.height) self.window.on_resize = self.projection.resize self.world = World() self.camera = Camera() self.world.add( GameItem( camera=self.camera, position=Origin, move=WobblyOrbit(32, 1, speed=-0.5), ) ) self.render = Render(self.world) self.render.init() pyglet.clock.schedule(self.update) self.clock_display = pyglet.clock.ClockDisplay() vs = VertexShader(join('flyinghigh', 'shaders', 'lighting.vert')) fs = FragmentShader(join('flyinghigh', 'shaders', 'lighting.frag')) shader = ShaderProgram(vs, fs) shader.use() def update(self, dt): # self.fpss.append(1/max(1e-3, dt)) dt = min(dt, 1 / 30) self.world.update(dt) self.window.invalid = True def draw(self): self.window.clear() self.projection.set_perspective(45) self.camera.look_at(Origin) self.render.draw() self.projection.set_screen() self.camera.reset() self.render.draw_hud(self.clock_display) return EVENT_HANDLED def stop(self): if self.window: self.window.close()
class Renderer(object): def __init__(self, client, map_size, minimap_size) -> None: self._client = client self._window = None self._map_size = map_size self._map_image = None self._minimap_size = minimap_size self._minimap_image = None self._mouse_x, self._mouse_y = None, None self._text_supply = None self._text_vespene = None self._text_minerals = None self._text_score = None self._text_time = None async def render(self, observation): render_data = observation.observation.render_data map_size = render_data.map.size map_data = render_data.map.data minimap_size = render_data.minimap.size minimap_data = render_data.minimap.data map_width, map_height = map_size.x, map_size.y map_pitch = -map_width * 3 minimap_width, minimap_height = minimap_size.x, minimap_size.y minimap_pitch = -minimap_width * 3 if not self._window: from pyglet.window import Window from pyglet.image import ImageData from pyglet.text import Label self._window = Window(width=map_width, height=map_height) self._window.on_mouse_press = self._on_mouse_press self._window.on_mouse_release = self._on_mouse_release self._window.on_mouse_drag = self._on_mouse_drag self._map_image = ImageData(map_width, map_height, 'RGB', map_data, map_pitch) self._minimap_image = ImageData(minimap_width, minimap_height, 'RGB', minimap_data, minimap_pitch) self._text_supply = Label('', font_name='Arial', font_size=16, anchor_x='right', anchor_y='top', x=self._map_size[0] - 10, y=self._map_size[1] - 10, color=(200, 200, 200, 255)) self._text_vespene = Label('', font_name='Arial', font_size=16, anchor_x='right', anchor_y='top', x=self._map_size[0] - 130, y=self._map_size[1] - 10, color=(28, 160, 16, 255)) self._text_minerals = Label('', font_name='Arial', font_size=16, anchor_x='right', anchor_y='top', x=self._map_size[0] - 200, y=self._map_size[1] - 10, color=(68, 140, 255, 255)) self._text_score = Label('', font_name='Arial', font_size=16, anchor_x='left', anchor_y='top', x=10, y=self._map_size[1] - 10, color=(219, 30, 30, 255)) self._text_time = Label('', font_name='Arial', font_size=16, anchor_x='right', anchor_y='bottom', x=self._minimap_size[0] - 10, y=self._minimap_size[1] + 10, color=(255, 255, 255, 255)) else: self._map_image.set_data('RGB', map_pitch, map_data) self._minimap_image.set_data('RGB', minimap_pitch, minimap_data) self._text_time.text = str( datetime.timedelta( seconds=(observation.observation.game_loop * 0.725) // 16)) if observation.observation.HasField('player_common'): self._text_supply.text = "{} / {}".format( observation.observation.player_common.food_used, observation.observation.player_common.food_cap) self._text_vespene.text = str( observation.observation.player_common.vespene) self._text_minerals.text = str( observation.observation.player_common.minerals) if observation.observation.HasField('score'): self._text_score.text = "{} score: {}".format( score_pb._SCORE_SCORETYPE.values_by_number[ observation.observation.score.score_type].name, observation.observation.score.score) await self._update_window() if self._client.in_game and (not observation.player_result ) and self._mouse_x and self._mouse_y: await self._client.move_camera_spatial( Point2((self._mouse_x, self._minimap_size[0] - self._mouse_y))) self._mouse_x, self._mouse_y = None, None async def _update_window(self): self._window.switch_to() self._window.dispatch_events() self._window.clear() self._map_image.blit(0, 0) self._minimap_image.blit(0, 0) self._text_time.draw() self._text_score.draw() self._text_minerals.draw() self._text_vespene.draw() self._text_supply.draw() self._window.flip() def _on_mouse_press(self, x, y, button, modifiers): if button != 1: # 1: mouse.LEFT return if x > self._minimap_size[0] or y > self._minimap_size[1]: return self._mouse_x, self._mouse_y = x, y def _on_mouse_release(self, x, y, button, modifiers): if button != 1: # 1: mouse.LEFT return if x > self._minimap_size[0] or y > self._minimap_size[1]: return self._mouse_x, self._mouse_y = x, y def _on_mouse_drag(self, x, y, dx, dy, buttons, modifiers): if not buttons & 1: # 1: mouse.LEFT return if x > self._minimap_size[0] or y > self._minimap_size[1]: return self._mouse_x, self._mouse_y = x, y
class Camera_test(MyTestCase): def setUp(self): self.window = Window( width=200, height=100, visible=False, caption="Camera_test setup") self.window.dispatch_events() glClearColor(0, 0, 0, 1) self.window.clear() self.world = World() self.camera = Camera((0, 0), 1) def tearDown(self): self.window.close() def test_constructor(self): camera = Camera((1, 2), 3, 4) self.assertEquals(camera.x, 1, "should init x") self.assertEquals(camera.y, 2, "should init y") self.assertEquals(camera.scale, 3, "should init scale") self.assertEquals(camera.angle, 4, "should init angle") def test_constructor_defaults_angle(self): camera = Camera((10, 20), 30) self.assertEquals(camera.angle, 0.0, "should init angle") def _draw_rect(self, backColor, polyColor, left, bottom, right, top): glClearColor( backColor[0]/255, backColor[1]/255, backColor[2]/255, 1.0) self.window.clear() verts = [ (left, bottom), (right, bottom), (right, top), (left, top), ] glColor3ub(*polyColor) glBegin(GL_TRIANGLE_FAN) for vert in verts: glVertex2f(*vert) glEnd() def test_world_projection_default(self): rect = (-0.2, -0.4, +0.6, +0.8) expectedRect = (90, 10, 129, 69) self.assert_world_projection(rect, expectedRect) def test_defect_pyglet_get_color_buffer_for_resized_windows(self): self.window.set_size(111, 222) self.window.dispatch_events() mgr = get_buffer_manager() col_buf = mgr.get_color_buffer() col_buf_size = col_buf.width, col_buf.height self.assertEquals(col_buf_size, (111, 222), "pyglet bug regression") def test_world_projection_strange_aspect(self): # create a new window, since # resizing the existing window doesn't work for some reason # even if we dispatch events. Default handlers? self.window.close() self.window = Window( width=100, height=200, visible=False, caption="world.test_projection_strange_aspect") self.window.dispatch_events() rect = (-0.2, -0.4, +0.6, +0.8) expectedRect = (40, 60, 79, 119) self.assert_world_projection(rect, expectedRect) def test_world_projection_offset(self): self.camera.x, self.camera.y = (+0.5, +0.3) rect = (-0.2, -0.4, +0.6, +0.8) expectedRect = (65, 25, 104, 84) self.assert_world_projection(rect, expectedRect) def test_world_projection_scale(self): self.camera.scale = 10 rect = (-1, -2, +3, +4) expectedRect = (95, 30, 114, 59) self.assert_world_projection(rect, expectedRect) def test_world_projection_angle(self): self.camera.angle = pi/2 rect = (-0.2, -0.4, +0.6, +0.8) expectedRect = (60, 20, 119, 59) self.assert_world_projection(rect, expectedRect) def test_world_projection_complicated(self): self.camera.angle = -pi/2 self.camera.scale = 10 self.camera.x, self.camera.y = (5, 6) rect = (-1, -2, +3, +4) expectedRect = (60, 20, 89, 39) self.assert_world_projection(rect, expectedRect)
class Application(object): ''' This class creates a window with an OpenGL context, and contains hooks for components to call to request updates as apart of the 'game loop.' :param size: is a tuple representing the default size of the window (width, height). :type size: 2-tuple of integers :param title: is the title text at the top of the window. :type title: str :param fullscreen: tells the window to start fullscren or not. :type fullscreen: boolean ''' def __init__(self, size=(DEFAULT_WIDTH, DEFAULT_HEIGHT), title='MegaMinerAI Bland Title Text', fullscreen=False): self.window = Window(width=size[0], height=size[1], caption=title, visible=True, fullscreen=fullscreen, resizable=True, style=Window.WINDOW_STYLE_DEFAULT, vsync=False, display=None, context=None, config=None) self.updates = [] def request_update_on_draw(self, procedure, order=50): ''' This method tells the application that whenever a draw occurs for the application, that *procedure* should be called. :param order: specifies when *procedure* should be called. All procedures with the same *order* will execute in a semi-random fashion after the previous *order* and before the next *order* value in the update queue. In general, all procedures should be called sometime before the :mod:`renderer`'s update() function is called. Procedures will be called with *order* from least to greatest. :type order: float or integer :param procedure: should not expect any arguments or an exception will be thrown. :type procedure: function or class method Example gameloop:: >>> app.request_update_on_draw(game.update_objects) >>> app.request_update_on_draw(game.do_input_stuff, 10) >>> app.request_update_on_draw(game.render_frame, 100) >>> app.run() 'processing user input' 'updating game objects' 'rendering frame' ''' self.updates += [(order, procedure)] self.updates.sort(key=lambda x: x[0]) def _update(self, dt): ''' This function is called at the start of every loop in the 'game loop.' It calls all the procedures that requested updates in the game loop. *dt* is the time since the last call. ''' # Forces a redraw # Trigger everything self.window.clear() for order, procedure in self.updates: procedure() def run(self): ''' This method starts the 'game loop.' It is a blocking function so at this, point all modules should have requested updates from the application or another thread should have been started. ''' pyglet.clock.schedule(self._update) pyglet.app.run()
class ImageViewer(object): """A simple class for viewing images using pyglet.""" def __init__(self, caption, height, width, monitor_keyboard=False, relevant_keys=None): """ Initialize a new image viewer. Args: caption (str): the caption/title for the window height (int): the height of the window width (int): the width of the window monitor_keyboard: whether to monitor events from the keyboard relevant_keys: the relevant keys to monitor events from Returns: None """ self.caption = caption self.height = height self.width = width self.monitor_keyboard = monitor_keyboard self.relevant_keys = relevant_keys self._window = None self._pressed_keys = [] self._is_escape_pressed = False @property def is_open(self): """Return a boolean determining if this window is open.""" return self._window is not None @property def is_escape_pressed(self): """Return True if the escape key is pressed.""" return self._is_escape_pressed @property def pressed_keys(self): """Return a sorted list of the pressed keys.""" return tuple(sorted(self._pressed_keys)) def _handle_key_event(self, symbol, is_press): """ Handle a key event. Args: symbol: the symbol in the event is_press: whether the event is a press or release Returns: None """ # remap the key to the expected domain symbol = KEY_MAP.get(symbol, symbol) # check if the symbol is the escape key if symbol == key.ESCAPE: self._is_escape_pressed = is_press return # make sure the symbol is relevant if self.relevant_keys is not None and symbol not in self.relevant_keys: return # handle the press / release by appending / removing the key to pressed if is_press: self._pressed_keys.append(symbol) else: self._pressed_keys.remove(symbol) def on_key_press(self, symbol, modifiers): """Respond to a key press on the keyboard.""" self._handle_key_event(symbol, True) def on_key_release(self, symbol, modifiers): """Respond to a key release on the keyboard.""" self._handle_key_event(symbol, False) def open(self): """Open the window.""" # create a window for this image viewer instance self._window = Window( caption=self.caption, height=self.height, width=self.width, vsync=False, resizable=True, ) # add keyboard event monitors if enabled if self.monitor_keyboard: self._window.event(self.on_key_press) self._window.event(self.on_key_release) self._window.set_exclusive_keyboard() def close(self): """Close the window.""" if self.is_open: self._window.close() self._window = None def show(self, frame): """ Show an array of pixels on the window. Args: frame (numpy.ndarray): the frame to show on the window Returns: None """ # check that the frame has the correct dimensions if len(frame.shape) != 3: raise ValueError('frame should have shape with only 3 dimensions') # open the window if it isn't open already if not self.is_open: self.open() # prepare the window for the next frame self._window.clear() self._window.switch_to() self._window.dispatch_events() # create an image data object image = ImageData(frame.shape[1], frame.shape[0], 'RGB', frame.tobytes(), pitch=frame.shape[1] * -3) # send the image to the window image.blit(0, 0, width=self._window.width, height=self._window.height) self._window.flip()
class Game(object): INITIAL_UPDATE_INTERVAL = UPDATE_INTERVAL def __init__(self): impl.funcs.load_resources() self.gameInfo = GameInfo() self.win = Window(FIELD_WIDTH, FIELD_HEIGHT) self.win.set_caption("snake") impl.funcs.setup_background_color() impl.funcs.setup_opengl_blend_func() self.gameField = GameField(self.gameInfo, self.win) self.menu = Menu(FIELD_WIDTH//2, FIELD_HEIGHT//2, self.game_start_callback, self.game_exit_callback, self.win) self._overlay = None self._update_interval = Game.INITIAL_UPDATE_INTERVAL @self.gameField.event def on_restart_snake(): unschedule(func=self.update) self._setup_overlay("restart") schedule_once(func=self.run_snake, delay=DELAY_FOR_NEW_RUN) @self.gameField.event def on_rerun_menu(): unschedule(func=self.update) #reset current handler self.win.pop_handlers() #and setup update handler self.win.push_handlers(self.menu) self.menu.start_bgrn_animation() @self.gameField.event def on_game_over(): unschedule(func=self.update) self._setup_overlay('game over...') schedule_once(func=self.game_exit_callback, delay=DELAY_FOR_EXIT) @self.gameField.event def on_score_up(): if self._update_interval > MAX_UPDATE_SPEED_INTERVAL: self._update_interval -= UPDATE_INTERVAL_SPEED_DX unschedule(func=self.update) schedule_interval(func=self.update,interval=self._update_interval) def _setup_overlay(self, text): self._overlay = BouncingLabel(FIELD_WIDTH//2,FIELD_HEIGHT//2,text,DEFAULT_OVERLAY_COLOR) self.win.pop_handlers() def on_draw(): self.win.clear() self._overlay.draw() self.win.push_handlers(on_draw) schedule_interval(func=self._overlay.update, interval=OVERLAY_UPDATE_INTERVAL) def game_start_callback(self): self._setup_overlay("start") schedule_once(func=self.run_snake, delay=DELAY_FOR_NEW_RUN) def game_exit_callback(self, *args): if self._overlay: unschedule(self._overlay.update) self._overlay = None self.win.pop_handlers() self.win.close() def start(self): self.win.push_handlers(self.menu) pyglet.app.run() def update(self, dt): if not self.gameInfo.pause: self.gameField.update(dt) def run_snake(self, *args): if self._overlay: unschedule(self._overlay.update) self._overlay = None #reset current handlers self.win.pop_handlers() self.gameInfo.pause = False self.gameField.reset() #setup new handlers self.win.push_handlers(self.gameField) #and setup update handler self._update_interval = Game.INITIAL_UPDATE_INTERVAL schedule_interval(func=self.update,interval=self._update_interval)
class ImageViewer(object): def __init__(self, width, height, display=None): from pyglet.window import Window self.sheet = SpriteSheet() self.display = display self.window = Window(width=width * self.sheet.BLOCK_WIDTH, height=height * self.sheet.BLOCK_WIDTH, display=self.display) self.isopen = True self.init_blend() def init_blend(self): from pyglet.gl import (GL_BLEND, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA, glBlendFunc, glEnable) glEnable(GL_BLEND) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) def render_state(self, state, x_offset=0, flip=True): import pyglet darken = pyglet.image.SolidColorImagePattern(color=(0, 0, 0, 128)) if flip: self.begin_flip() for i, entity in enumerate(state.entities): if entity is None: continue y, x = divmod(i, state.width) neighbours = [None] * 4 neighbours[1] = state[x, y - 1] neighbours[0] = state[x, y + 1] neighbours[3] = state[x - 1, y] neighbours[2] = state[x + 1, y] if state.tsu_rules: if y == 0: neighbours = [None] * 4 elif y == 1: neighbours[1] = None sprite = self.sheet.get_sprite(entity, neighbours) sprite.blit( (x + x_offset) * self.sheet.BLOCK_WIDTH, (state.height - 1 - y) * self.sheet.BLOCK_WIDTH, ) if state.tsu_rules and y == 0: mask = darken.create_image(self.sheet.BLOCK_WIDTH + 1, self.sheet.BLOCK_WIDTH) mask.blit( (x + x_offset) * self.sheet.BLOCK_WIDTH, (state.height - 1 - y) * self.sheet.BLOCK_WIDTH, ) for i, deal in enumerate(state.deals): for j, entity in enumerate(deal): neighbours = [None] * 4 # Deals are usually not rendered "sticky" # neighbours[2 + j] = deal[1 - j] sprite = self.sheet.get_sprite(entity, neighbours) sprite.blit( (state.width + 2 + j + x_offset) * self.sheet.BLOCK_WIDTH, (state.height - 1 - 2 * i) * self.sheet.BLOCK_WIDTH, ) if flip: self.end_flip() def begin_flip(self): self.window.clear() self.window.switch_to() self.window.dispatch_events() def end_flip(self): self.window.flip() def save_screenshot(self, filename): from pyglet.image import get_buffer_manager get_buffer_manager().get_color_buffer().save(filename) def close(self): if self.isopen: self.window.close() self.isopen = False def __del__(self): self.close()
class Renderer: def __init__(self, client, map_size, minimap_size): self._client = client self._window = None self._map_size = map_size self._map_image = None self._minimap_size = minimap_size self._minimap_image = None self._mouse_x, self._mouse_y = None, None self._text_supply = None self._text_vespene = None self._text_minerals = None self._text_score = None self._text_time = None async def render(self, observation): render_data = observation.observation.render_data map_size = render_data.map.size map_data = render_data.map.data minimap_size = render_data.minimap.size minimap_data = render_data.minimap.data map_width, map_height = map_size.x, map_size.y map_pitch = -map_width * 3 minimap_width, minimap_height = minimap_size.x, minimap_size.y minimap_pitch = -minimap_width * 3 if not self._window: # pylint: disable=C0415 from pyglet.image import ImageData from pyglet.text import Label from pyglet.window import Window self._window = Window(width=map_width, height=map_height) self._window.on_mouse_press = self._on_mouse_press self._window.on_mouse_release = self._on_mouse_release self._window.on_mouse_drag = self._on_mouse_drag self._map_image = ImageData(map_width, map_height, "RGB", map_data, map_pitch) self._minimap_image = ImageData(minimap_width, minimap_height, "RGB", minimap_data, minimap_pitch) self._text_supply = Label( "", font_name="Arial", font_size=16, anchor_x="right", anchor_y="top", x=self._map_size[0] - 10, y=self._map_size[1] - 10, color=(200, 200, 200, 255), ) self._text_vespene = Label( "", font_name="Arial", font_size=16, anchor_x="right", anchor_y="top", x=self._map_size[0] - 130, y=self._map_size[1] - 10, color=(28, 160, 16, 255), ) self._text_minerals = Label( "", font_name="Arial", font_size=16, anchor_x="right", anchor_y="top", x=self._map_size[0] - 200, y=self._map_size[1] - 10, color=(68, 140, 255, 255), ) self._text_score = Label( "", font_name="Arial", font_size=16, anchor_x="left", anchor_y="top", x=10, y=self._map_size[1] - 10, color=(219, 30, 30, 255), ) self._text_time = Label( "", font_name="Arial", font_size=16, anchor_x="right", anchor_y="bottom", x=self._minimap_size[0] - 10, y=self._minimap_size[1] + 10, color=(255, 255, 255, 255), ) else: self._map_image.set_data("RGB", map_pitch, map_data) self._minimap_image.set_data("RGB", minimap_pitch, minimap_data) self._text_time.text = str( datetime.timedelta( seconds=(observation.observation.game_loop * 0.725) // 16)) if observation.observation.HasField("player_common"): self._text_supply.text = f"{observation.observation.player_common.food_used} / {observation.observation.player_common.food_cap}" self._text_vespene.text = str( observation.observation.player_common.vespene) self._text_minerals.text = str( observation.observation.player_common.minerals) if observation.observation.HasField("score"): # pylint: disable=W0212 self._text_score.text = f"{score_pb._SCORE_SCORETYPE.values_by_number[observation.observation.score.score_type].name} score: {observation.observation.score.score}" await self._update_window() if self._client.in_game and (not observation.player_result ) and self._mouse_x and self._mouse_y: await self._client.move_camera_spatial( Point2((self._mouse_x, self._minimap_size[0] - self._mouse_y))) self._mouse_x, self._mouse_y = None, None async def _update_window(self): self._window.switch_to() self._window.dispatch_events() self._window.clear() self._map_image.blit(0, 0) self._minimap_image.blit(0, 0) self._text_time.draw() self._text_score.draw() self._text_minerals.draw() self._text_vespene.draw() self._text_supply.draw() self._window.flip() def _on_mouse_press(self, x, y, button, _modifiers): if button != 1: # 1: mouse.LEFT return if x > self._minimap_size[0] or y > self._minimap_size[1]: return self._mouse_x, self._mouse_y = x, y def _on_mouse_release(self, x, y, button, _modifiers): if button != 1: # 1: mouse.LEFT return if x > self._minimap_size[0] or y > self._minimap_size[1]: return self._mouse_x, self._mouse_y = x, y def _on_mouse_drag(self, x, y, _dx, _dy, buttons, _modifiers): if not buttons & 1: # 1: mouse.LEFT return if x > self._minimap_size[0] or y > self._minimap_size[1]: return self._mouse_x, self._mouse_y = x, y
class Gameloop(object): def __init__(self, options): self.options = options self.window = None self.fpss = [] self.time = 0.0 self.level = None def prepare(self, options): self.window = Window( fullscreen=options.fullscreen, vsync=options.vsync, visible=False, resizable=True) self.window.on_draw = self.draw_window self.world = World() self.player = Player(self.world) self.camera = GameItem( position=origin, update=CameraMan(self.player, (3, 2, 0)), ) self.level_loader = Level(self) success = self.start_level(1) if not success: logging.error("ERROR, can't load level 1") sys.exit(1) self.update(1/60) self.window.push_handlers(KeyHandler(self.player)) self.render = Render(self.world, self.window, self.camera) self.render.init() self.music = Music() self.music.load() self.music.play() def run(self): pyglet.clock.schedule(self.update) self.window.set_visible() self.window.invalid = False pyglet.app.run() def update(self, dt): if self.options.print_fps: self.fpss.append(1/max(1e-6, dt)) dt = min(dt, 1 / 30) self.time += dt for item in self.world: if hasattr(item, 'update'): item.update(item, dt, self.time) if self.player_at_exit(): self.world.remove(self.player) pyglet.clock.schedule_once( lambda *_: self.start_level(self.level + 1), 1.0 ) self.window.invalid = True def start_level(self, n): success = self.level_loader.load(self.world, n) if not success: logging.info('No level %d' % (n,)) self.stop() return False self.level = n pyglet.clock.schedule_once( lambda *_: self.world.add(self.player), 2.0, ) return True def player_at_exit(self): items = self.world.collision.get_items(self.player.position) if any(hasattr(item, 'exit') for item in items): dist2_to_exit = dist2_from_int_ords(self.player.position) if dist2_to_exit < EPSILON2: return True return False def draw_window(self): self.window.clear() self.render.draw_world() if self.options.display_fps: self.render.draw_hud() self.window.invalid = False return EVENT_HANDLED def stop(self): if self.window: self.window.close() if self.options.print_fps: print ' '.join("%6.1f" % (dt, ) for dt in self.fpss)
if state: print "\tspace is pushed" if not state: print "\tspace is released" # Utworzenie InputManagera i włączenie go do pygleta manager = InputManager() window = Window() window.on_key_press = manager.key_pressed window.on_key_release = manager.key_released # Tworzymy 3 obiekty obserwujące ops1 = ConcreteInputObserver('ops1') ops2 = ConcreteInputObserver('ops2') ops3 = ConcreteInputObserver('ops3') # dodajemy obserwatorów manager.register_observer(ops1) manager.register_observer(ops2) manager.register_observer(ops3) # usuwamy obserwatorów manager.unregister_observer(ops1) manager.unregister_observer(ops2) # zostaje tylko trzech obserwatorów # uruchamiamy aplikację print "Możesz sprawdzić działanie klawszy wsad, strzałek oraz spacji" window.clear() pyglet.app.run()
print "\tspace is pushed" if not state: print "\tspace is released" # Utworzenie InputManagera i włączenie go do pygleta manager = InputManager() window = Window() window.on_key_press = manager.key_pressed window.on_key_release = manager.key_released # Tworzymy 3 obiekty obserwujące ops1 = ConcreteInputObserver('ops1') ops2 = ConcreteInputObserver('ops2') ops3 = ConcreteInputObserver('ops3') # dodajemy obserwatorów manager.register_observer(ops1) manager.register_observer(ops2) manager.register_observer(ops3) # usuwamy obserwatorów manager.unregister_observer(ops1) manager.unregister_observer(ops2) # zostaje tylko trzech obserwatorów # uruchamiamy aplikację print "Możesz sprawdzić działanie klawszy wsad, strzałek oraz spacji" window.clear() pyglet.app.run()
class Application(object): ''' This class creates a window with an OpenGL context, and contains hooks for components to call to request updates as apart of the 'game loop.' :param size: is a tuple representing the default size of the window (width, height). :type size: 2-tuple of integers :param title: is the title text at the top of the window. :type title: str :param fullscreen: tells the window to start fullscren or not. :type fullscreen: boolean ''' def __init__(self, size=(DEFAULT_WIDTH, DEFAULT_HEIGHT), title='MegaMinerAI Bland Title Text', fullscreen=False): self.window = Window(width=size[0], height=size[1], caption=title, visible=True, fullscreen=fullscreen, resizable=True, style=Window.WINDOW_STYLE_DEFAULT, vsync=False, display=None, context=None, config=None) self.updates = [] # Set up the event dispatcher self.ed = EventDispatcher() self.ed.register_class_for_events(self) # Build the game loader self.loader = gameloader.GameLoader(self.ed) #Build the renderer self.renderer = renderer.Renderer() # Request updates self.request_update_on_draw(self.renderer.init_frame, 0) self.request_update_on_draw(self.renderer.draw_frame, 100) @event_handler def on_run_gamelog(self, data): print('handler') game_name = data['gameName'].lower() path = os.path.join(config.setting['plugin directory'], game_name, 'main.py') self.game = imp.load_source(game_name, path) self.game.load(self, data) return True def request_update_on_draw(self, procedure, order=50): ''' This method tells the application that whenever a draw occurs for the application, that *procedure* should be called. :param order: specifies when *procedure* should be called. All procedures with the same *order* will execute in a semi-random fashion after the previous *order* and before the next *order* value in the update queue. In general, all procedures should be called sometime before the :mod:`renderer`'s update() function is called. Procedures will be called with *order* from least to greatest. :type order: float or integer :param procedure: should not expect any arguments or an exception will be thrown. :type procedure: function or class method Example gameloop:: >>> app.request_update_on_draw(game.update_objects) >>> app.request_update_on_draw(game.do_input_stuff, 10) >>> app.request_update_on_draw(game.render_frame, 100) >>> app.run() 'processing user input' 'updating game objects' 'rendering frame' ''' self.updates += [(order, procedure)] self.updates.sort(key=lambda x: x[0]) def _update(self, dt): ''' This function is called at the start of every loop in the 'game loop.' It calls all the procedures that requested updates in the game loop. *dt* is the time since the last call. ''' # Forces a redraw # Trigger everything self.window.clear() for order, procedure in self.updates: procedure() def run(self, glog_list=[]): ''' This method starts the 'game loop.' It is a blocking function so at this, point all modules should have requested updates from the application or another thread should have been started. ''' self.ed.dispatch_event('on_load_gamelog_file', glog_list) pyglet.clock.schedule(self._update) pyglet.app.run()