Пример #1
0
    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)
        window.connect('button-press-event', self.mouse_pressed)

        self.drawing_area.connect('draw', self.draw)

        window.show_all()
Пример #2
0
    def on_draw_hud(self, c, w):
        for i, t in enumerate(self.draw_times):
            c.draw_line(w.win_size - Vec(4 * i - 2, 0),
                        relative=(0, -t * 1000),
                        width=2,
                        color=to_rgba(RED, .3))

        for i, t in enumerate(self.world_times):
            c.draw_line(w.win_size - Vec(4 * i, 0),
                        relative=(0, -t * 1000),
                        width=2,
                        color=to_rgba(YELLOW, .3))

        # 25, 30, 60 FPS marks
        graph_width = 4 * len(self.draw_times)
        for fps, color in ((25, ORANGE), (30, GREEN), (60, BLUE)):
            c.draw_line(w.win_size - Vec(graph_width, 1000 / fps),
                        relative=(graph_width, 0),
                        width=.5,
                        color=to_rgba(color, .3))

        now = time()
        dt = now - self.draw_last
        self.draw_last = now
        self.draw_times.appendleft(dt)
Пример #3
0
    def draw(c, w, cell, pos=None):
        if cell.is_food or cell.is_ejected_mass:
            return
        text_pos = Vec(pos) if pos else w.world_to_screen_pos(cell.pos)

        # draw cell's mass
        if cell.name:
            text_pos.iadd(Vec(0, (info_size + nick_size(cell, w)) / 2))
        c.draw_text(text_pos, '%i' % cell.mass, align='center', outline=(BLACK, 2), size=info_size)

        # draw needed mass to eat it splitted
        text_pos.iadd(Vec(0, info_size))
        c.draw_text(text_pos, '(%i)' % ((cell.mass*2*1.33)-w.player.total_mass), align='center', outline=(BLACK, 2), size=info_size/1.5)
Пример #4
0
    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
            # if self.player.is_alive or (self.player.center.x == 0 and self.player.center.y == 0) or not self.player.scale == 1.0: # HACK due to bug: player scale is sometimes wrong (sent by server?) in spectate mode
            window_scale = max(self.win_size.x / 1920, self.win_size.y / 1080)
            new_screen_scale = self.player.scale * window_scale * self.screen_zoom_scale
            self.screen_scale = lerp_smoothing(self.screen_scale,
                                               new_screen_scale, 0.1, 0.0001)

            smoothing_factor = 0.1
            if self.player.is_alive:
                smoothing_factor = 0.3

            self.world_center.x = lerp_smoothing(self.world_center.x,
                                                 self.player.center.x,
                                                 smoothing_factor, 0.01)
            self.world_center.y = lerp_smoothing(self.world_center.y,
                                                 self.player.center.y,
                                                 smoothing_factor, 0.01)

            self.world = self.player.world
        elif self.world.size:
            new_screen_scale = min(
                self.win_size.x / self.world.size.x,
                self.win_size.y / self.world.size.y) * self.screen_zoom_scale
            self.screen_scale = lerp_smoothing(self.screen_scale,
                                               new_screen_scale, 0.1, 0.0001)
            self.world_center = self.world.center
        else:
            # happens when the window gets drawn before the world got updated
            self.screen_scale = self.screen_zoom_scale
            self.world_center = Vec(0, 0)
Пример #5
0
 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)
Пример #6
0
    def on_draw_hud(self, c, w):
        c.draw_text((10, 30), 'Team', align='left', color=WHITE, outline=(BLACK, 2), size=27)

        # draw player position in main view
        for i, player in enumerate(list(self.tagar_client.player_list.values())):
            c.draw_text((10, 60 + TEAM_OVERLAY_PADDING * i), player.nick,
                        align='left', color=WHITE, outline=(BLACK, 2), size=18)

            if player.total_mass > 0:
                mass_color = GRAY
                mass_text = 'Mass: ' + str('%.2f' % player.total_mass)
            else:
                mass_text = 'Dead'
                mass_color = RED

            c.draw_text((10, 75 + TEAM_OVERLAY_PADDING * i), mass_text,
                        align='left', color=mass_color, outline=(BLACK, 2), size=12)

            c.draw_text((10, 88 + TEAM_OVERLAY_PADDING * i), '#' + player.party_token,
                        align='left', color=GRAY, outline=(BLACK, 2), size=12)

            button = Button(90, 75 - 12 + TEAM_OVERLAY_PADDING * i, 50, 25, "JOIN")
            button.id = player
            w.register_button(button)
            c.draw_button(button)

            if self.tagar_client.player.is_alive and player.is_alive:
                # draw lines to team members
                client_pos = w.world_to_screen_pos(w.player.center)
                pos = w.world_to_screen_pos(Vec(player.position_x, player.position_y))
                c.draw_line(client_pos, pos, width=2, color=GREEN)

                # TODO draw names
                text_size = 12
                border_x = border_y = text_size

                if not border_x < pos.x < w.win_size.x-border_x or not border_y < pos.y < w.win_size.x-border_x:
                    side_out = abs(pos.x/pos.y) > w.win_size.x/w.win_size.y
                    alignment = 'left' if pos.x < w.win_size.x/2 else 'right'

                    if side_out and abs(pos.x-client_pos.x) > 0.0:
                        x = min(max(pos.x, border_x), w.win_size.x-border_x)
                        pos.y -= client_pos.y
                        pos.y *= abs((x-client_pos.x)/(pos.x-client_pos.x))
                        pos.y += client_pos.y
                        pos.x = x
                    elif abs(pos.y-client_pos.y) > 0.0:
                        y = min(max(pos.y, border_y), w.win_size.y-border_y)
                        pos.x -= client_pos.x
                        pos.x *= abs((y-client_pos.y)/(pos.y-client_pos.y))
                        pos.x += client_pos.x
                        pos.y = y

                    dist = ((w.player.center.x-player.position_x)**2 + (w.player.center.y-player.position_y)**2)**0.5

                    c.draw_text(pos, "%s (%.1f / %.1f)" % (player.nick, player.total_mass, dist), align=alignment, color=WHITE, outline=(BLACK, 2), size=text_size)
Пример #7
0
    def draw_minimap_backgound(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_map(world_pos):
                pos_from_top_left = world_pos - w.world.top_left
                return minimap_offset + pos_from_top_left * minimap_scale

            # minimap background
            c.fill_rect(minimap_offset,
                        size=minimap_size,
                        color=to_rgba(DARK_GRAY, .8))

            # outline the area visible in window
            c.stroke_rect(world_to_map(w.screen_to_world_pos(Vec(0, 0))),
                          world_to_map(w.screen_to_world_pos(w.win_size)),
                          width=1,
                          color=BLACK)
Пример #8
0
    def test_visible_area(self):
        player = Player()

        # simple test

        win = WindowMock()

        player.scale = win.screen_scale
        player.world.top_left = win.tl
        player.world.bottom_right = win.br

        ptl, pbr = player.visible_area

        rtl = win.screen_to_world_pos(zero)
        rbr = win.screen_to_world_pos(screen)

        self.assertAlmostEqual(ptl.x, rtl.x)
        self.assertAlmostEqual(ptl.y, rtl.y)
        self.assertAlmostEqual(pbr.x, rbr.x)
        self.assertAlmostEqual(pbr.y, rbr.y)

        # complex test

        win = WindowMock(Vec(123, 234), Vec(-34.5, 45.6))

        player.scale = win.screen_scale = 2.3
        player.world.top_left = win.tl
        player.world.bottom_right = win.br

        ptl, pbr = player.visible_area

        rtl = win.screen_to_world_pos(zero)
        rbr = win.screen_to_world_pos(screen)

        self.assertAlmostEqual(ptl.x, rtl.x)
        self.assertAlmostEqual(ptl.y, rtl.y)
        self.assertAlmostEqual(pbr.x, rbr.x)
        self.assertAlmostEqual(pbr.y, rbr.y)
Пример #9
0
    def on_draw_minimap(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_map(world_pos):
                pos_from_top_left = world_pos - w.world.top_left
                return minimap_offset + pos_from_top_left * minimap_scale

            # draw cells
            cells = self.tagar_client.team_world.cells.copy()
            for cell in cells.values():
                if cell.cid not in w.world.cells:
                    if cell.cid in self.tagar_client.team_cids:
                        c.fill_circle(world_to_map(cell.pos),
                                      cell.size * minimap_scale,
                                      color=to_rgba(cell.color, 0.7))
                    else:
                        alpha = .66 if cell.mass > (self.tagar_client.player.total_mass * 0.66) else 0.33
                        c.stroke_circle(world_to_map(cell.pos),
                                        cell.size * minimap_scale,
                                        color=to_rgba(cell.color, alpha))

            # draw lines to team members
            if self.tagar_client.player.is_alive:
                for i, player in enumerate(list(self.tagar_client.player_list.values())):
                    if player.is_alive:
                        c.draw_line(world_to_map(w.player.center),
                                    world_to_map(Vec(player.position_x, player.position_y)),
                                    width=1, color=GREEN)

            # draw names
            for i, player in enumerate(list(self.tagar_client.player_list.values())):
                if player.is_alive:
                    c.draw_text(world_to_map(Vec(player.position_x, player.position_y)), player.nick,
                                align='center', color=WHITE, outline=(BLACK, 2), size=8)
Пример #10
0
    def on_draw_minimap(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_map(world_pos):
                pos_from_top_left = world_pos - w.world.top_left
                return minimap_offset + pos_from_top_left * minimap_scale

            for cell in w.world.cells.values():
                c.stroke_circle(world_to_map(cell.pos),
                                cell.size * minimap_scale,
                                color=to_rgba(cell.color, .8))
Пример #11
0
    def on_draw_hud(c, w):
        if w.player.is_alive and w.screen_zoom_scale != 1.0:
            window_scale = max(w.win_size.x / 1920, w.win_size.y / 1080)
            screen_scale_no_zoom = w.player.scale * window_scale

            def screen_to_world_pos(screen_pos):
                return (screen_pos - w.screen_center) \
                    .idiv(screen_scale_no_zoom).iadd(w.world_center)

            # outline the area visible in window
            c.stroke_rect(
                w.world_to_screen_pos(screen_to_world_pos(Vec(0, 0))),
                w.world_to_screen_pos(screen_to_world_pos(w.win_size)),
                width=1,
                color=LIGHT_GRAY)
Пример #12
0
    def on_draw_cells(self, c, w):
        if len(w.player.own_ids) <= 1:
            return  # dead or only one cell, no re-merge time to display

        now = time()
        for cell in w.player.own_cells:
            split_for = now - cell.spawn_time
            # formula by HungryBlob
            ttr = max(30, cell.size // 5) - split_for
            if ttr < 0:
                continue
            pos = w.world_to_screen_pos(cell.pos)
            pos.isub(Vec(0, (info_size + nick_size(cell, w)) / 2))
            c.draw_text(pos, 'TTR %.1fs after %.1fs' % (ttr, split_for),
                        align='center', outline=(BLACK, 2), size=info_size)
Пример #13
0
 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)
Пример #14
0
 def __init__(self, tl=Vec(-10, 10), br=Vec(-10, 10)):
     self.tl = tl
     self.br = br
     self.world_center = (br + tl) / 2
     self.screen_center = screen / 2
     self.screen_scale = 1
Пример #15
0
from unittest import TestCase

from agarnet.vec import Vec
from agarnet.world import Cell, Player, World

screen = Vec(1920, 1080)
zero = Vec(0, 0)


class WindowMock:
    def __init__(self, tl=Vec(-10, 10), br=Vec(-10, 10)):
        self.tl = tl
        self.br = br
        self.world_center = (br + tl) / 2
        self.screen_center = screen / 2
        self.screen_scale = 1

    # taken from gagar, same as in official client
    def screen_to_world_pos(self, screen_pos):
        return (screen_pos - self.screen_center) \
            .idiv(self.screen_scale).iadd(self.world_center)


class CellTest(TestCase):
    def test_lt(self):
        self.assertLess(Cell(1), Cell(2))
        self.assertLess(Cell(2, size=10), Cell(1, size=11))


class WorldTest(TestCase):
    def test_world(self):