def main(): global win clock.schedule(rabbyt.add_time) win = Window(width=800, height=600) rabbyt.set_default_attribs() lawn = Lawn() wind = Wind() magicEventRegister(win, events, list(lawn)) while not win.has_exit: tick = clock.tick() win.dispatch_events() lawn.update(tick) wind.update(tick) events.ConsumeEventQueue() rabbyt.clear((1, 1, 1)) lawn.draw() win.flip()
def main(): global fps_display win = Window(width=800, height=600) clock.schedule(rabbyt.add_time) rabbyt.set_default_attribs() bg = Background() fps_display = clock.ClockDisplay() while not win.has_exit: tick = clock.tick() win.dispatch_events() bg.update(tick) rabbyt.clear((bg.color)) bg.draw() fps_display.draw() win.flip()
def test_motion(self): w = Window(200, 200) try: w.push_handlers(self) while not w.has_exit: w.dispatch_events() finally: w.close() self.user_verify('Pass test?', take_screenshot=False)
def test_resize(self): w = Window(200, 200, resizable=True) try: w.push_handlers(self) while not w.has_exit: window_util.draw_client_border(w) w.flip() w.dispatch_events() finally: w.close() self.user_verify('Pass test?', take_screenshot=False)
def main(): clock.schedule(rabbyt.add_time) win = Window(width=800, height=600) rabbyt.set_default_attribs() lawn = NewLawn() while not win.has_exit: tick = clock.tick() win.dispatch_events() lawn.update(tick) rabbyt.clear((1, 1, 1)) lawn.draw() win.flip()
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
def test_caption(self): try: w1 = Window(400, 200, resizable=True) w2 = Window(400, 200, resizable=True) count = 1 w1.set_caption('Window caption %d' % count) w2.set_caption(u'\u00bfHabla espa\u00f1ol?') last_time = time.time() while not (w1.has_exit or w2.has_exit): if time.time() - last_time > 1: count += 1 w1.set_caption('Window caption %d' % count) last_time = time.time() w1.dispatch_events() w2.dispatch_events() finally: w1.close() w2.close() self.user_verify('Pass test?', take_screenshot=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 App(object): def __init__(self, pmap): self.world = World(pmap) self.win = Window(width=pmap['bounds'][2], height=pmap['bounds'][3]) # pyglet.clock.set_fps_limit(10) # pyglet.clock.set_fps_limit(60) self.win.push_handlers(self.on_key_press) self.fullscreen = False def main_loop(self): self.world.annealing.kickoff() while not (self.win.has_exit or self.world.finished): self.win.dispatch_events() if (not self.world.finished) and (not self.world.pause): self.world.update() if (self.world.showvisuals): self.world.draw() pyglet.clock.tick() self.win.flip() self.win.close() def on_key_press(self, symbol, modifiers): # IDEA more key toggles, make it a dictionary if symbol == key.D: self.world.showdebug = not self.world.showdebug elif symbol == key.F: self.fullscreen = not self.fullscreen self.win.set_fullscreen(fullscreen=self.fullscreen) self.world.draw() elif symbol == key.G: self.world.showgrid = not self.world.showgrid elif symbol == key.S: self.world.pause = not self.world.pause elif symbol == key.U: self.world.showUI = not self.world.showUI elif symbol == key.V: self.world.showvisuals = not self.world.showvisuals
def test_set_visible(self): w = Window(200, 200) try: w.push_handlers(WindowEventLogger()) w.dispatch_events() self.user_verify('Is the window visible?', take_screenshot=False) w.set_visible(False) w.dispatch_events() self.user_verify('Is the window no longer visible?', take_screenshot=False) w.set_visible(True) w.dispatch_events() self.user_verify('Is the window visible again?', take_screenshot=False) finally: w.close()
for tag in tag.getElementsByTagName('path'): self.objects.append(Curve(tag.getAttribute('d'))) def draw(self): glPushMatrix() glTranslatef(0, 1024, 0) glScalef(1, -1, 1) for object in self.objects: object.draw() glPopMatrix() w = Window(width=1024, height=768) # XXX move this into display list glEnable(GL_LINE_SMOOTH) glEnable(GL_BLEND) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) glHint(GL_LINE_SMOOTH_HINT, GL_DONT_CARE) dirname = os.path.dirname(__file__) svg = SVG(os.path.join(dirname, 'hello_world.svg')) clock.set_fps_limit(10) while not w.has_exit: clock.tick() glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) w.dispatch_events() svg.draw() w.flip()
# But note that all times will be in *seconds*, not milliseconds like when we # use pygame.time.get_ticks(). clock.schedule(rabbyt.add_time) window = Window(width=640, height=480) rabbyt.set_default_attribs() car = rabbyt.Sprite("car.png") # Rabbyt automatically detected that we are using pyglet, and used pyglet # to load the texture. assert isinstance(car.texture, image.Texture) car.xy = (320, 240) # Fade the car in after one second. car.alpha = rabbyt.lerp(0.0, 1.0, startt=1, endt=2) # Rotate the car from 0 to 360 over three seconds, then repeat. car.rot = rabbyt.lerp(0, 360, dt=3, extend="repeat") while not window.has_exit: clock.tick() window.dispatch_events() rabbyt.clear((1,1,1)) car.render() window.flip()
sprites = [] numsprites = int(sys.argv[1]) for i in range(numsprites): x = random.randint(0, w.width - img.width) y = random.randint(0, w.height - img.height) s = BouncySprite(x, y, img.width, img.height, img) s.dx = random.randint(-10, 10) s.dy = random.randint(-10, 10) sprites.append(s) view = FlatView.from_window(w, sprites=sprites) view.fx, view.fy = w.width / 2, w.height / 2 t = 0 numframes = 0 while 1: if w.has_exit: print 'FPS:', clock.get_fps() print 'us per sprite:', float(t) / (numsprites * numframes) * 1000000 break t += clock.tick() w.dispatch_events() for s in sprites: s.update() view.clear() view.draw() w.flip() numframes += 1 w.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 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)
def on_key_press(symbol, modifiers): if symbol == key.BACKSPACE: interp.backspace() else: return True window.push_handlers(on_key_press) def blink_cursor(dt): cursor = layout.document.get_element('cursor') if cursor.style['background-color']: del cursor.style['background-color'] else: cursor.style['background-color'] = 'black' clock.schedule_interval(blink_cursor, 0.5) glClearColor(1, 1, 1, 1) window.set_visible() while not window.has_exit: window.dispatch_events() clock.tick() glClear(GL_COLOR_BUFFER_BIT) layout.draw() window.flip()
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 ExpWindow(object): def __init__(self, background_color=dark_gray, clock=mono_clock.get_time): # lazy load, partially to avoid auto-formatter that wants to # do imports, *then* dict setting from pyglet import gl from pyglet.window import Window self._background_color = Vector4f(background_color) self.clock = clock self.current_time = 0 self.prev_time = 0 # can bump down `samples` if performance is hurting config = gl.Config(depth_size=0, double_buffer=True, alpha_size=8, sample_buffers=1, samples=4, vsync=False, major_version=3, minor_version=3) display = pyglet.canvas.get_display() screen = display.get_screens()[0] self._win = Window(resizable=False, fullscreen=True, screen=screen, config=config, style='borderless', vsync=True) self._win.event(self.on_key_press) atexit.register(self._on_close) self.context = mgl.create_context(require=int('%i%i0' % (config.major_version, config.minor_version))) self.context.viewport = (0, 0, self.width, self.height) self.context.enable(mgl.BLEND) self.frame_period # do this before we've drawn anything # in principle, should be disconnected from the window # but we're saving time & mental energy self.cam = Camera(projection=height_ortho(self.width, self.height)) def on_key_press(self, symbol, modifiers): if symbol == pyglet.window.key.ESCAPE: sys.exit(1) def _on_close(self): if self._win.context: self._win.close() def flip(self): self._win.switch_to() self._win.dispatch_events() self._win.flip() self.context.clear(*self._background_color) current_time = self.clock() self.prev_time = self.current_time self.current_time = current_time return self.current_time def close(self): self._win.close() @property def dt(self): return self.current_time - self.prev_time def set_mouse_visible(self, val): self._win.set_mouse_visible(val) @property def width(self): return self._win.width @property def height(self): return self._win.height @property def background_color(self): return self._background_color @background_color.setter def background_color(self, val): if len(val) != 4: raise ValueError('Background color must be RGBA.') self._background_color.xyzw = val @property def frame_period(self): # get a whole-number version of the frame period # very coarse and fragile, should get this from the # the video mode, e.g. glfw.get_video_mode if not hasattr(self, '_frame_period'): possible = [60.0, 144.0, 240.0] # TODO: infer from machine... vals = [] for _ in range(20): self.flip() vals.append(self.dt) # chop off the first few, which are not reflective of the # "real" FPS avg = 1/(sum(vals[5:])/float(len(vals[5:]))) dff = [abs(avg - p) for p in possible] fps = [v for v, d in zip(possible, dff) if d == min(dff)] if not len(fps): self._frame_period = 1/60.0 # default else: self._frame_period = 1/fps[0] return self._frame_period
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 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: """ While we aren't networking this game it's better to learn this structure now rather than later. Even if you never plan on learning how to network your games this is still a very good architecture to use. This Client class should be considered completely separate from the Game. It is just a way of interacting with the game. The game should not depend on anything in this class. Working like this will help you keep your code much cleaner and, as stated before, networkable. You could also make multiple clients using different technologies. In our case we are using pyglet and rabbyt libraries, but it wouldn't be difficult to make a client using pygame or even just the consol (for a text mode). """ def __init__(self, game): # While the game needs to work independently of the client the client # can't work independently of the game. The client will be sending # input to the game as well as looking up different elements (such as # all the blocks so we can draw them and tell the game when we click on # one). self.game = game # Setup our pyglet window. self.window = Window(width=self.game.size_xy[0]*20, height=self.game.size_xy[1]*20+50) self.window.set_caption("Mines") self.window.on_close = sys.exit # The default pyglet OpenGL display is setup a bit different than how # rabbyt would like, thus rabbyt.set_default_attribs rabbyt.set_default_attribs() # Using pyglet for input is really easy. When you get further down # you'll see GameContorl inherits from EventDispatcher. That's how # window.push_handlers does the magic as we'll see further down. self.ctrl = GameContorl(self) self.window.push_handlers(self.ctrl) # Here we have some sprites we are going to use for the client. For # bigger games I think it's better to separate stuff like this out; # but this is quite small and not an issue. self.smile_face = rabbyt.Sprite("data/smile.png") self.smile_face.x = self.window.width/2 self.smile_face.y = self.window.height-25 self.dead_face = rabbyt.Sprite("data/smile_dead.png") self.dead_face.xy = self.smile_face.xy self.won_face = rabbyt.Sprite("data/smile_won.png") self.won_face.xy = self.smile_face.xy # That sprite stuff was pretty self explanatory. It is also very basic. # I'm not going to be going into much depth with rabbyt in these # tutorials so you may want to check out the rabbyt documentation from # http://matthewmarshall.org/projects/rabbyt/ # Very cool and elegant stuff there. Check it out! self.clock = Clock() self.clock.set_fps_limit(20) self.window.push_handlers(self.clock) self.time = 0 self.clock.schedule(self._add_time) self.setup() def setup(self): """ Just like the setup in the Game class this one fills out the block data. But wait, why do we have to do this again? Remeber how in the GameBlock we only had stuff related to the game engine; no display stuff? Well, we need display stuff for the client - that's why we have ClientBlock! As you'll see soon the ClientBlock sorta wraps the GameBlock to provide the graphical stuff we need. """ self.blocks = {} for key,b in self.game.blocks.items(): self.blocks[key] = ClientBlock(self, b) def _add_time(self, dt): """ This is kept track of so we can pass it onto rabbyt (so animation works) """ self.time += dt def loop(self): """ And here is our main game loop! In case you are new to game programming this is what is called every frame. This is where we will handle the display and stuff. """ # clock.tick is used for keeping track of time and limiting the frame # rate. self.clock.tick() self.window.dispatch_events() # And this is where that mysterious "time" comes in. This way rabbyt # knows how much time has passed and can do the awesome animations. rabbyt.set_time(self.time) # If you are new to this sort of thing rabbyt.clear clears the screen # (erases what was drawn last loop). We pass white as the color that we # want to clear it with. rabbyt.clear((1,1,1,1)) # And now we draw our blocks and smile face. for b in self.blocks.values(): b.draw() if self.game.gameover == True: if self.game.won == False: self.dead_face.render() else: self.won_face.render() else: self.smile_face.render() # This draws the buffer onto the screen. Without this we would be # staring at a blank screen. self.window.flip() def press_block(self, block): """ This is called by the Control as we will see later. Pretty simple and even unneeded. But this is where you could add cool effects for when you click on a block if you wannted to. (That's the reasion I have it) """ self.game.press_block(block.gameblock) def retry(self): """ Re-sets up the game. """ self.game.setup() self.setup()
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(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 Gameloop(object): instance = None def __init__(self): Gameloop.instance = self self.window = None self.camera = None self.world = None self.renderer = None self.paused = False self.fps_display = None Keyboard.handlers.update({ key.PAGEUP: lambda: self.camera.zoom(2.0), key.PAGEDOWN: lambda: self.camera.zoom(0.5), key.ESCAPE: self.quit_game, key.PAUSE: self.toggle_pause, key.F12: lambda: save_screenshot(self.window), }) def init(self, name, version): clock.set_fps_limit(FPS_LIMIT) self.fps_display = clock.ClockDisplay() self.camera = Camera((0, 0), 800) self.renderer = Renderer(self.camera) caption = '%s v%s' % (name, version) self.window = Window( caption=caption, fullscreen=True, visible=False) self.window.on_key_press = on_key_press self.window.push_handlers(Keyboard.keystate) graphics = load_graphics() self.world = World() builder = LevelBuilder() seed(1) builder.build(self.world, 75, graphics) self.world.player = Player() self.world.player.add_to_space(self.world.space, (0, 200), 0) self.world.chunks.update(self.world.player.chunks) def dispose(self): if self.window: self.window.close() def run(self): try: self.window.set_visible() while not self.window.has_exit: self.window.dispatch_events() clock.tick() if self.world and not self.paused: self.world.tick(1/FPS_LIMIT) if self.world and hasattr(self.world, 'player'): player_position = self.world.player.chunks[0].body.position self.camera.x, self.camera.y = player_position self.camera.angle = atan2( player_position.x, player_position.y) self.camera.update() if self.renderer: aspect = ( self.window.width / self.window.height) self.renderer.draw(self.world, aspect) self.camera.hud_projection( (self.window.width, self.window.height)) self.fps_display.draw() self.window.flip() finally: self.dispose() def toggle_pause(self): self.paused = not self.paused def quit_game(self): self.window.has_exit = True