Пример #1
0
def draw_ground_gradient():
    """Base ground gradient (debug, would be removed lately)."""
    global ctx
    ctx_old = ctx
    ctx = ctx_ground
    ctx.set_operator(cairo.Operator.SOURCE)
    pattern = cairo.LinearGradient(0, 0, WIDTH, 0)
    pattern.add_color_stop_rgba(0, *BASE_COLORS[0])
    pattern.add_color_stop_rgba(0.6, *blend(BASE_COLORS[0],
                                            BASE_COLORS[1], 0.3))
    pattern.add_color_stop_rgba(1, *BASE_COLORS[1])
    ctx.set_source(pattern)
    ctx.rectangle(0, HEIGHT * 0.8, WIDTH, HEIGHT)
    ctx.fill()
    ctx.set_operator(cairo.Operator.DEST_IN)
    pattern = cairo.LinearGradient(0, HEIGHT * 0.8, 0, HEIGHT)
    pattern.add_color_stop_rgba(0, 0, 0, 0, 0)
    pattern.add_color_stop_rgba(0.5, 1, 1, 1, 0.3)
    pattern.add_color_stop_rgba(1, 1, 1, 1, 1)
    ctx.set_source(pattern)
    ctx.rectangle(0, HEIGHT * 0.8, WIDTH, HEIGHT)
    ctx.fill()
    ctx = ctx_old
    ctx.set_source_surface(surface_ground)
    ctx.rectangle(0, 0, WIDTH, HEIGHT)
    ctx.fill()
Пример #2
0
def draw_sky():
    """Draw the sky background with the sun."""
    # horizon gradient
    pattern = cairo.LinearGradient(0, 0, 0, HEIGHT)
    pattern.add_color_stop_rgba(0, *lighten(BASE_COLORS[3], 0.05, 1))
    pattern.add_color_stop_rgba(0.4, *BASE_COLORS[3])
    pattern.add_color_stop_rgba(1, *lighten(BASE_COLORS[2], 0))
    ctx.set_source(pattern)
    ctx.rectangle(0, 0, WIDTH, HEIGHT)
    ctx.fill()

    # right side gradient
    color_from = blend(BASE_COLORS[0], BASE_COLORS[1], 0.5)
    pattern = cairo.LinearGradient(0, HEIGHT, WIDTH * (2 / 3), 0)
    pattern.add_color_stop_rgba(0, *opaque(color_from, -0.2))
    pattern.add_color_stop_rgba(1, *opaque(color_from, -1))
    ctx.set_source(pattern)
    ctx.rectangle(0, 0, WIDTH, HEIGHT)
    ctx.fill()

    # the sun
    sun_x, sun_y = WIDTH * 0.5, HEIGHT * 0.33
    sun_color = lighten(BASE_COLORS[4], 0.5)
    r = HEIGHT
    pattern = cairo.RadialGradient(sun_x, sun_y, 0, sun_x, sun_y, r)
    pattern.add_color_stop_rgba(0, *lighten(BASE_COLORS[4], 0.5))
    for stop, dark in np.linspace((0, 0), (1, -1)):
        stop = stop ** (stop * 4.6 + 1)
        pattern.add_color_stop_rgba(stop, *opaque(sun_color, dark))
    ctx.set_source(pattern)
    ctx.rectangle(0, 0, WIDTH, HEIGHT)
    ctx.fill()
Пример #3
0
def draw_ground():
    """Draw the ground with buildings on it."""
    draw_ground_gradient()
    cam_y = HEIGHT * 0.5
    num_x, num_y = 50, 50
    density = 0.8
    points = generate_ground_points(WIDTH * 1.5, HEIGHT * 3,
                                    num_x, num_y, cam_y)
    color_magic = lighten(saturate(BASE_COLORS[0], 0.1), 0.8)
    for i, (x, y) in enumerate(points):
        # calculate colors from x, y coordinate
        blend_x = (i // num_x) / num_x
        blend_y = (i % num_y) / num_y * 2 - 1
        blend_y = min(0.5, max(-0.5, blend_y)) + 0.5
        color_l = blend(color_magic, BASE_COLORS[0], blend_x)
        color_r = (
            blend(BASE_COLORS[2], BASE_COLORS[1], blend_x / 0.6)
            if blend_x < 0.6 else
            blend(BASE_COLORS[1], BASE_COLORS[0], blend_x / 0.6 - 1)
        )
        color = blend(color_r, color_l, blend_y)
        color = opaque(color, (blend_x - 1) * 0.8 + 0.2)
        if i // num_y < num_y - 2 and i % num_x < num_x - 2:
            # draw solid ground
            face_coords = (
                points[i], points[i + 1],
                points[i + num_x + 1], points[i + num_x]
            )
            draw_poly(ctx, face_coords, color, outline_darken=-0.1)
            random_height = abs(random.gauss(0.5, 0.2) - 0.5)
            random_width = abs(random.gauss(0.5, 0.1))
            # draw a building
            if random.random() < density * max(0.3, 1 - blend_x):
                w, h = perspective_point(
                    -WIDTH * random_width / 7, -HEIGHT * random_height * 0.8,
                    0, focal_l * WIDTH * 1.5, (1 - blend_x) * HEIGHT * 15
                )
                draw_house(*points[i], w, h, color)
Пример #4
0
def draw_wall(x, y, width, height, num_horiz, num_vert,
              color_main, color_dark=None):
    """Draw a wall of bricks."""
    color_dark = color_dark or color_main
    # build a grid
    brick_width = width / num_horiz / 2
    brick_height = height / num_vert
    x_coords = [
        x + i * brick_width + (random.random() - 0.5) * brick_width * 0.2
        for i in range(num_horiz * 2 + 2)
    ]
    y_coords = [
        y + i * brick_height + (random.random() - 0.5) * brick_height * 0.01
        for i in range(num_vert + 1)
    ]

    # draw bricks
    for i, (y1, y2) in enumerate(zip(y_coords[:-1], y_coords[1:])):
        for j in range(num_horiz):
            x1, x2 = x_coords[j * 2 + i % 2], x_coords[(j + 1) * 2 + i % 2]
            coords = ((x1, y1), (x2 - 1, y1), (x2 - 1, y2 - 1), (x1, y2 - 1))
            blend_ratio = abs(random.gauss(0.5, 0.2) - 0.5)
            cur_color = blend(color_main, color_dark, blend_ratio)
            draw_poly(ctx, coords, cur_color, outline_darken=0.2)
Пример #5
0
def draw_altar(x_p, y_p, w_p, h_p):
    """Draw far wall with an "altar". """
    # inner arc
    color = lighten(saturate(BASE_COLORS[1], -0.1), 0.1)
    ctx.set_source_rgba(*color)
    ctx.rectangle(x_p + w_p / 2, y_p + h_p * 2, -w_p, -h_p)
    ctx.fill()
    # top brick rays
    rev_ang = (h_p > 0) * math.pi
    rev_blend = 1 + (h_p > 0) * 1.5
    rays_color = blend(BASE_COLORS[1], BASE_COLORS[3], 0.5 / rev_blend)
    ctx.set_source_rgba(*rays_color)
    ctx.set_line_width(1.5)
    ctx.arc(x_p, y_p + h_p, abs(w_p) / 32, -math.pi + rev_ang, 0 - rev_ang)
    ctx.stroke()
    for i in range(13):
        phi = i / 12 * math.pi
        x1, y1 = polar2vec(-w_p / 20, phi + rev_ang)
        x2, y2 = polar2vec(-w_p / 4, phi + rev_ang)
        ctx.move_to(x1 + x_p, y1 + y_p + h_p)
        ctx.line_to(x2 + x_p, y2 + y_p + h_p)
        ctx.set_line_width(1)
        ctx.stroke()
    # top altar shadow
    pattern = cairo.RadialGradient(x_p, y_p + h_p, w_p * 0.13,
                                   x_p, y_p + h_p, w_p / 4)
    pattern.add_color_stop_rgba(0, 0, 0, 0, 0)
    pattern.add_color_stop_rgba(1, 0, 0, 0, 0.9)
    pattern.add_color_stop_rgba(1, 0, 0, 0, 0)
    ctx.set_source(pattern)
    ctx.rectangle(x_p + w_p / 2, y_p + h_p * 2, -w_p, -h_p)
    ctx.fill()
    br = 0.405
    # outer arc
    color = lighten(BASE_COLORS[2], 0)
    prev_paths_l, prev_paths_r = draw_verona_arc(
        x_p, y_p, w_p, h_p,
        saturate(lighten(color, 0.12), -0.1),
        saturate(lighten(color, -0.5), -0.1),
        0.042, (0, 1), (0.23, 1.78),
        brick_ratio=1 - br, brick_depth=0,
    )
    # far wall
    draw_wall(
        x_p - w_p / 2, y_p - max(0, -h_p), w_p, abs(h_p),
        7, 8,
        lighten(saturate(BASE_COLORS[2], -0.42), -0.08),
        BASE_COLORS[1],
    )
    # bottom brick
    color = lighten(saturate(BASE_COLORS[1], -0.1), 0.1)
    ctx.set_source_rgba(*color)
    ctx.rectangle(x_p + w_p * br / 2, y_p + h_p - h_p / 2, -w_p * br, -h_p / 8)
    ctx.fill()
    # side altar shadows
    pattern = cairo.LinearGradient(x_p - w_p * br / 2, y_p,
                                   x_p + w_p * br / 2, y_p)
    pattern.add_color_stop_rgba(0, 0, 0, 0, 0)
    pattern.add_color_stop_rgba(0, 0, 0, 0, 0.7)
    pattern.add_color_stop_rgba(0.2, 0, 0, 0, 0)
    pattern.add_color_stop_rgba(0.8, 0, 0, 0, 0)
    pattern.add_color_stop_rgba(1, 0, 0, 0, 0.7)
    pattern.add_color_stop_rgba(1, 0, 0, 0, 0)
    ctx.set_source(pattern)
    ctx.rectangle(x_p + w_p / 2, y_p + h_p * 1.005, -w_p, -h_p * 0.63)
    ctx.fill()
Пример #6
0
def draw_verona_arc(x, y, width, height, color_main, color_dark,
                    rand_amount=0.25, grad_main=(0, 0),
                    grad_depth=(-0.18, -0.18),
                    brick_ratio=0.27, brick_depth=0.5,
                    prev_paths=(None, None), prev_colors=(None, None)):
    """Draw a single arc in Verona style."""
    paths_r = list(zip(*generate_arc_paths(x, y, width / 2, height,
                                           8, 4, 3, brick_ratio)))
    paths_l = list(zip(*generate_arc_paths(x, y, -width / 2, height,
                                           8, 4, 3, brick_ratio)))
    # ceiling to the previous arc
    prev_color_main, prev_color_dark = prev_colors
    draw_ceiling(
        prev_color_main, prev_color_dark,
        paths_l, paths_r, *prev_paths
    )
    # a lamp
    draw_lamp(x, y + height * 1.56, width / 16, -height * 0.5,
              prev_color_main, prev_color_dark)
    for paths in (paths_r, paths_l):
        # left and right half-arcs
        for i, coords in enumerate(zip(paths[:-2], paths[1:-1])):
            (((x1o, y1o), (x1i, y1i), (x1d, y1d)),
             ((x2o, y2o), (x2i, y2i), (x2d, y2d))) = coords
            coords = [(x1o, y1o), (x2o, y2o), (x2i, y2i),
                      (x2d, y2d), (x1d, y1d), (x1i, y1i)]
            if brick_depth == 0:
                del coords[3:5]
            grad_ratio = (grad_main[1] - grad_main[0]) * i / (len(paths) - 2) + grad_main[0]
            rand_ratio = random.gauss(grad_ratio, rand_amount)
            blend_ratio = max(0, min(1, (rand_ratio)))
            cur_color = blend(color_main, color_dark, blend_ratio)
            draw_poly(ctx, coords, cur_color, outline_darken=0.29)
            # brick depth
            if brick_depth > 0:
                coords = ((x1i, y1i), (x2i, y2i),
                          (x2d, y2d), (x1d, y1d))
                shadow_ratio = (grad_depth[1] - grad_depth[0]) * i / (len(paths) - 2) + grad_depth[0]
                cur_color = lighten(cur_color, shadow_ratio)
                draw_poly(ctx, coords, cur_color, outline_darken=0.5)
    # top brick
    coords = (
        paths_r[-1][0], paths_r[-2][0], paths_r[-2][1], paths_r[-2][2],
        (paths_r[-1][0][0],
         paths_r[-2][2][1] + (paths_r[-2][2][1] - paths_r[0][2][1]) * 0.02),
        paths_l[-2][2], paths_l[-2][1], paths_l[-2][0],
    )
    cur_color = blend(color_main, color_dark, grad_main[1])
    draw_poly(ctx, coords, cur_color, outline_darken=0.29)
    # top brick depth
    coords = (
        (paths_r[-1][0][0],
         paths_r[-2][1][1] + (paths_r[-2][1][1] - paths_r[0][1][1]) * 0.02),
        paths_r[-2][1], paths_r[-2][2],
        (paths_r[-1][0][0],
         paths_r[-2][2][1] + (paths_r[-2][2][1] - paths_r[0][2][1]) * 0.02),
        paths_l[-2][2], paths_l[-2][1],
    )
    if brick_depth > 0:
        draw_poly(ctx, coords, lighten(cur_color, grad_depth[1]),
                  outline_darken=0.29)
    return paths_l, paths_r