def on_draw_hud(self, c, w): if w.world.size: minimap_w = w.win_size.x / 5 minimap_size = Vec(minimap_w, minimap_w) minimap_scale = minimap_size.x / w.world.size.x minimap_offset = w.win_size - minimap_size def world_to_mm(world_pos): pos_from_top_left = world_pos - w.world.top_left return minimap_offset + pos_from_top_left * minimap_scale line_width = c.get_line_width() c.set_line_width(1) # minimap border c.set_source_rgba(*to_rgba(LIGHT_GRAY, .5)) c.rectangle(*as_rect(minimap_offset, size=minimap_size)) c.stroke() # the area visible in window c.rectangle( *as_rect(world_to_mm(w.screen_to_world_pos(Vec(0, 0))), world_to_mm(w.screen_to_world_pos(w.win_size)))) c.stroke() for cell in w.world.cells.values(): draw_circle_outline(c, world_to_mm(cell.pos), cell.size * minimap_scale, color=to_rgba(cell.color, .8)) c.set_line_width(line_width)
def __init__(self, world): self.world = world self.player = None # the focused player, or None to show full world # the class instance on which to call on_key_pressed and on_mouse_moved self.input_subscriber = None # same for draw_background, draw_cells, draw_hud self.draw_subscriber = None self.win_size = Vec(1000, 1000 * 9 / 16) self.screen_center = self.win_size / 2 self.screen_scale = 1 self.world_center = Vec(0, 0) self.mouse_pos = Vec(0, 0) window = Gtk.Window() window.set_title('agar.io') window.set_default_size(self.win_size.x, self.win_size.y) window.connect('delete-event', Gtk.main_quit) self.drawing_area = Gtk.DrawingArea() window.add(self.drawing_area) window.set_events(Gdk.EventMask.POINTER_MOTION_MASK) window.connect('key-press-event', self.key_pressed) window.connect('motion-notify-event', self.mouse_moved) self.drawing_area.connect('draw', self.draw) window.show_all()
def on_draw_hud(self, c, w): c.set_line_width(2) c.set_source_rgba(*to_rgba(RED, .3)) for i, t in enumerate(self.draw_times): c.move_to(*(w.win_size - Vec(4 * i - 2, 0))) c.rel_line_to(0, -t * 1000) c.stroke() c.set_source_rgba(*to_rgba(YELLOW, .3)) for i, t in enumerate(self.world_times): c.move_to(*(w.win_size - Vec(4 * i, 0))) c.rel_line_to(0, -t * 1000) c.stroke() # 25, 30, 60 FPS marks c.set_line_width(.5) graph_width = 4 * len(self.draw_times) for fps, color in ((25, ORANGE), (30, GREEN), (60, BLUE)): c.set_source_rgba(*to_rgba(color, .3)) c.move_to(*(w.win_size - Vec(graph_width, 1000 / fps))) c.rel_line_to(graph_width, 0) c.stroke() now = time() dt = now - self.draw_last self.draw_last = now self.draw_times.appendleft(dt)
def mouse_moved(self, _, event): """Called by GTK. Set input_subscriber to handle this.""" if not self.input_subscriber: return self.mouse_pos = Vec(event.x, event.y) pos_world = self.screen_to_world_pos(self.mouse_pos) self.input_subscriber.on_mouse_moved(pos=self.mouse_pos, pos_world=pos_world)
def on_draw_cells(self, c, w): for cell in w.world.cells.values(): if cell.is_food or cell.is_ejected_mass: continue pos = w.world_to_screen_pos(cell.pos) if cell.name: pos.iadd(Vec(0, 12)) text = '%i mass' % cell.mass draw_text_center(c, pos, text)
def on_draw_cells(self, c, w): if len(self.player.own_ids) <= 1: return # dead or only one cell, no remerge time to display now = time() for cell in self.player.own_cells: split_for = now - self.split_times[cell.cid] # formula by DebugMonkey ttr = (self.player.total_mass * 20 + 30000) / 1000 - split_for if ttr < 0: continue pos = w.world_to_screen_pos(cell.pos) text = 'TTR %.1fs after %.1fs' % (ttr, split_for) draw_text_center(c, Vec(0, -12).iadd(pos), text)
def recalculate(self): alloc = self.drawing_area.get_allocation() self.win_size.set(alloc.width, alloc.height) self.screen_center = self.win_size / 2 if self.player: # any client is focused window_scale = max(self.win_size.x / 1920, self.win_size.y / 1080) self.screen_scale = self.player.scale * window_scale self.world_center = self.player.center self.world = self.player.world elif self.world.size: self.screen_scale = min(self.win_size.x / self.world.size.x, self.win_size.y / self.world.size.y) self.world_center = self.world.center else: # happens when the window gets drawn before the world got updated self.screen_scale = 1 self.world_center = Vec(0, 0)
class WorldViewer(object): """ Draws one world and handles keys/mouse. Does not poll for events itself. Calls input_subscriber.on_{key_pressed|mouse_moved}() methods on key/mouse input. Calls draw_subscriber.on_draw_{background|cells|hud}() methods when drawing. """ INFO_SIZE = 300 def __init__(self, world): self.world = world self.player = None # the focused player, or None to show full world # the class instance on which to call on_key_pressed and on_mouse_moved self.input_subscriber = None # same for draw_background, draw_cells, draw_hud self.draw_subscriber = None self.win_size = Vec(1000, 1000 * 9 / 16) self.screen_center = self.win_size / 2 self.screen_scale = 1 self.world_center = Vec(0, 0) self.mouse_pos = Vec(0, 0) window = Gtk.Window() window.set_title('agar.io') window.set_default_size(self.win_size.x, self.win_size.y) window.connect('delete-event', Gtk.main_quit) self.drawing_area = Gtk.DrawingArea() window.add(self.drawing_area) window.set_events(Gdk.EventMask.POINTER_MOTION_MASK) window.connect('key-press-event', self.key_pressed) window.connect('motion-notify-event', self.mouse_moved) self.drawing_area.connect('draw', self.draw) window.show_all() def focus_player(self, player): """Follow this client regarding center and zoom.""" self.player = player self.world = player.world def show_full_world(self, world=None): """ Show the full world view instead of one client. :param world: optionally update the drawn world """ self.player = None if world: self.world = world def key_pressed(self, _, event): """Called by GTK. Set input_subscriber to handle this.""" if not self.input_subscriber: return val = event.keyval try: char = chr(val) except ValueError: char = '' self.input_subscriber.on_key_pressed(val=val, char=char) def mouse_moved(self, _, event): """Called by GTK. Set input_subscriber to handle this.""" if not self.input_subscriber: return self.mouse_pos = Vec(event.x, event.y) pos_world = self.screen_to_world_pos(self.mouse_pos) self.input_subscriber.on_mouse_moved(pos=self.mouse_pos, pos_world=pos_world) def world_to_screen_pos(self, world_pos): return (world_pos - self.world_center) \ .imul(self.screen_scale).iadd(self.screen_center) def screen_to_world_pos(self, screen_pos): return (screen_pos - self.screen_center) \ .idiv(self.screen_scale).iadd(self.world_center) def recalculate(self): alloc = self.drawing_area.get_allocation() self.win_size.set(alloc.width, alloc.height) self.screen_center = self.win_size / 2 if self.player: # any client is focused window_scale = max(self.win_size.x / 1920, self.win_size.y / 1080) self.screen_scale = self.player.scale * window_scale self.world_center = self.player.center self.world = self.player.world elif self.world.size: self.screen_scale = min(self.win_size.x / self.world.size.x, self.win_size.y / self.world.size.y) self.world_center = self.world.center else: # happens when the window gets drawn before the world got updated self.screen_scale = 1 self.world_center = Vec(0, 0) def draw(self, _, c): if self.draw_subscriber: self.recalculate() self.draw_subscriber.on_draw_background(c, self) self.draw_subscriber.on_draw_cells(c, self) self.draw_subscriber.on_draw_hud(c, self)