예제 #1
0
        def get_end_point(
                scroll: Gtk.ScrolledWindow,
                target: Gtk.Widget) -> int:
            talloc = target.get_allocation()
            adjustment = scroll.get_vadjustment()
            start_point = adjustment.get_value()

            page_size = adjustment.get_page_size()
            if start_point <= talloc.y \
                    and (talloc.y+talloc.height) <= (start_point+page_size):
                # If all parts of the target widget content are visible,
                # no need to animate the scroll.
                return -1
            else:
                if talloc.y > start_point:
                    # If the height of the target widget is greater than the
                    # height of its container, scroll to the top-left
                    # coordinates of the widget. Otherwise, scroll to the
                    # bottom-right coordinates of the widget.
                    if talloc.height > page_size:
                        end_point = talloc.y
                    else:
                        end_point = min(adjustment.get_upper()-page_size,
                                        talloc.y+talloc.height-page_size)
                else:
                    end_point = talloc.y

            return end_point
예제 #2
0
    def scroll_to(scroll: Gtk.ScrolledWindow,
                  target: Gtk.Widget,
                  duration: int = 600) -> bool:
        """Animate the scroll for duration in milliseconds."""
        target = target.get_allocation()
        adjustment = scroll.get_vadjustment()
        start_point = adjustment.get_value()

        page_size = adjustment.get_page_size()
        if start_point <= target.y \
                and (target.y+target.height) <= (start_point+page_size):
            # If all parts of the target widget content are visible,
            # no need to animate the scroll.
            return False
        else:
            if target.y > start_point:
                # If the height of the target widget is greater than the
                # height of its container, scroll to the top-left coordinates
                # of the widget. Otherwise, scroll to the bottom-right
                # coordinates of the widget.
                if target.height > page_size:
                    end_point = target.y
                else:
                    end_point = min(adjustment.get_upper() - page_size,
                                    target.y + target.height - page_size)
            else:
                end_point = target.y

            # Stop the current animating when the same widget requested to be
            # animated again before it has finished animating
            scroll.end_point = end_point

        frame_clock = scroll.get_frame_clock()
        start_time = frame_clock.get_frame_time()
        end_time = start_time + 1000 * duration

        def animate(widget: Gtk.Widget, frame_clock: Gdk.FrameClock) -> bool:
            current_time = frame_clock.get_frame_time()
            if current_time < end_time \
                    and adjustment.get_value() != end_point \
                    and widget.end_point == end_point:
                t = (current_time - start_time) / (end_time - start_time)
                t = Animation.ease_out_cubic(t)
                adjustment.set_value(start_point + t *
                                     (end_point - start_point))
                return GLib.SOURCE_CONTINUE
            else:
                return GLib.SOURCE_REMOVE

        scroll.add_tick_callback(animate)

        return False
예제 #3
0
def draw(widget: Gtk.Widget, cr: cairo.Context):
    if not world.map:
        return

    player_x = world.player.x
    player_y = world.player.y

    allocation = widget.get_allocation()
    tile_width = allocation.width / world.map_width
    tile_height = allocation.height / world.map_height

    # clear drawing
    cr.set_source_rgb(1, 1, 1)
    cr.paint()

    # draw shadow
    shadow_surface = cairo.ImageSurface(cairo.Format.ARGB32, allocation.width,
                                        allocation.height)
    scr = cairo.Context(shadow_surface)
    scr.set_line_width(1)
    scr.set_source_rgb(0, 0, 0)
    for y, row in enumerate(world.map):
        for x, tile in enumerate(row):
            if tile == "#":
                left = x * tile_width
                top = y * tile_height
                right = left + tile_width
                bottom = top + tile_height
                shadow_points = []
                for dest_x, dest_y in itertools.product([left, right],
                                                        [top, bottom]):
                    other_x = {left: right, right: left}[dest_x]
                    other_y = {top: bottom, bottom: top}[dest_y]
                    if line_goes_through_border(player_x, player_y, dest_x, dest_y, other_x, top, bottom) \
                            or line_goes_through_border(player_y, player_x, dest_y, dest_x, other_y, left, right):
                        continue
                    shadow_points.append((dest_x, dest_y))
                if len(shadow_points) == 3:
                    for i in range(len(shadow_points)):
                        if shadow_points[i] == (shadow_points[(i - 1) % 3][0], shadow_points[(i + 1) % 3][1]) \
                                or shadow_points[i] == (shadow_points[(i + 1) % 3][0], shadow_points[(i - 1) % 3][1]):
                            del shadow_points[i]
                            break
                elif len(shadow_points) == 4:
                    continue
                for i, shadow_point in enumerate(
                        extend_shadow_points(shadow_points, allocation)):
                    if i == 0:
                        scr.move_to(*shadow_point)
                    else:
                        scr.line_to(*shadow_point)
                scr.fill()
    cr.set_source_surface(shadow_surface)
    cr.mask(cairo.SolidPattern(0, 0, 0, .6))
    cr.fill()

    # draw tiles
    cr.set_line_width(1)
    for y, row in enumerate(world.map):
        for x, tile in enumerate(row):
            if tile == "#":
                cr.set_source_rgb(.9, 0, 0)
                cr.rectangle(x * tile_width, y * tile_height, tile_width,
                             tile_height)
                cr.fill_preserve()
                cr.set_source_rgba(0, 0, 0)
                cr.stroke()

    for player in world.players.values():
        collides = False
        for y, row in enumerate(world.map):
            for x, tile in enumerate(row):
                if tile == "#":
                    left = x * tile_width
                    top = y * tile_height
                    right = left + tile_width
                    bottom = top + tile_height
                    if collision_rect_line(Rectangle(left, right, top,
                                                     bottom), player_x,
                                           player_y, player.x, player.y):
                        collides = True
                        break
            if collides:
                break
        if not collides:
            draw_player(cr, player)

    draw_player(
        cr,
        Player(player_x, player_y, world.player.rotation, world.player.health))

    for bullet in world.bullets:
        draw_bullet(cr, bullet)