├── .gitignore ├── canvas_bridge.py ├── devices.py ├── hexacircles.py ├── kuler.py ├── lollipops.py ├── pixelstorm.py ├── triangles.py └── tron_lines.py /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.pyc 3 | -------------------------------------------------------------------------------- /canvas_bridge.py: -------------------------------------------------------------------------------- 1 | try: 2 | from canvas import * 3 | except ImportError: 4 | # We're in NodeBox 5 | def begin_updates(): 6 | pass 7 | 8 | def end_updates(): 9 | pass 10 | 11 | set_fill_color = fill 12 | fill_rect = rect 13 | fill_ellipse = oval 14 | set_stroke_color = stroke 15 | set_line_width = strokewidth 16 | move_to = moveto 17 | 18 | 19 | def draw_rect(x, y, width, height): 20 | """capture and reset current fill color""" 21 | clr = fill() 22 | nofill() 23 | rect(x, y, width, height) 24 | fill(clr) 25 | 26 | def draw_ellipse(x, y, size_x, size_y): 27 | """capture and reset current fill color""" 28 | clr = fill() 29 | nofill() 30 | oval(x, y, size_x, size_y) 31 | fill(clr) 32 | 33 | set_size = size 34 | 35 | -------------------------------------------------------------------------------- /devices.py: -------------------------------------------------------------------------------- 1 | # pythonista doubles pixels on a retina display, so you really only need half size 2 | ipad = (512.0, 512.0) 3 | ipad_r = (1024.0, 1024.0) 4 | ipad_r_ios7 = (1262.0, 1262.0) 5 | iphone = (160.0, 240.0) 6 | iphone_r = (320.0, 480.0) 7 | iphone_5 = (320.0, 568.0) 8 | iphone_5_ios7 = (372.0, 696.0) 9 | mbp_r = (1440.0, 900.0) 10 | cinema = (1280.0, 800.0) 11 | -------------------------------------------------------------------------------- /hexacircles.py: -------------------------------------------------------------------------------- 1 | import canvas 2 | import random 3 | import math 4 | 5 | from devices import * 6 | from kuler import * 7 | 8 | random.seed() 9 | 10 | width, height = cinema 11 | circle_size = 256.0 12 | step = math.sqrt(circle_size**2 - (circle_size / 2.0)**2) 13 | 14 | palette = random.choice(themes) 15 | 16 | canvas.begin_updates() 17 | 18 | canvas.set_size(width, height) 19 | canvas.set_fill_color(*palette.darkest) 20 | canvas.fill_rect(0, 0, width, height) 21 | 22 | for x in range(100): 23 | r, g, b = random.choice(palette.colors) 24 | a = random.random() * 0.5 + 0.25 25 | canvas.set_fill_color(r, g, b, a) 26 | origin_x = random.random() * width 27 | origin_y = random.random() * height 28 | csize = random.random() * (width / 8.0) + (width / 16.0) 29 | canvas.fill_ellipse(origin_x, origin_y, csize, csize) 30 | 31 | def rstrokedline(start_x, start_y, end_x, end_y): 32 | line_width = random.random() * 0.25 + 0.25 33 | canvas.set_line_width(line_width) 34 | r, g, b = palette.lightest 35 | a = random.random() * 0.25 + 0.05 36 | canvas.set_stroke_color(r, g, b, a) 37 | canvas.draw_line(start_x, start_y, end_x, end_y) 38 | 39 | def hexacircle(start_x, start_y): 40 | r, g, b = random.choice(palette.colors) 41 | 42 | canvas.set_fill_color(r, g, b, random.random() * 0.75 + 0.25) 43 | s_r, s_g, s_b = palette.lightest 44 | canvas.set_stroke_color(s_r, s_g, s_b, random.random() * 0.50 + 0.50) 45 | canvas.set_line_width(random.random() * 0.25 + 0.25) 46 | circle = (start_x - (0.5 * circle_size), 47 | start_y - (0.5 * circle_size), 48 | circle_size, circle_size) 49 | canvas.draw_ellipse(*circle) 50 | canvas.fill_ellipse(*circle) 51 | 52 | # draw lines 53 | rstrokedline(start_x, start_y - circle_size, start_x, start_y + circle_size) 54 | rstrokedline(start_x - step, start_y, start_x + step, start_y) 55 | 56 | rstrokedline(start_x - step, start_y - (0.5 * circle_size), start_x + step, start_y + (0.5 * circle_size)) 57 | rstrokedline(start_x - step, start_y + (0.5 * circle_size), start_x + step, start_y - (0.5 * circle_size)) 58 | 59 | rstrokedline(start_x - step, start_y + (1.5 * circle_size), start_x + step, start_y - (1.5 * circle_size)) 60 | rstrokedline(start_x - step, start_y - (1.5 * circle_size), start_x + step, start_y + (1.5 * circle_size)) 61 | 62 | rstrokedline(start_x - step, start_y + (2.5 * circle_size), start_x + step, start_y - (2.5 * circle_size)) 63 | rstrokedline(start_x - step, start_y - (2.5 * circle_size), start_x + step, start_y + (2.5 * circle_size)) 64 | 65 | rstrokedline(start_x - (3.0 * step), start_y + (0.5 * circle_size), start_x + (3.0 * step), start_y - (0.5 * circle_size)) 66 | rstrokedline(start_x - (3.0 * step), start_y - (0.5 * circle_size), start_x + (3.0 * step), start_y + (0.5 * circle_size)) 67 | 68 | for x in xrange(int(math.ceil(width/circle_size))+1): 69 | for y in xrange(int(math.ceil(height/circle_size))+1): 70 | center_x = x * (2.0 * step) 71 | center_y = y * circle_size 72 | hexacircle(center_x, center_y) 73 | hexacircle(center_x + step, center_y + (0.5 * circle_size)) 74 | 75 | canvas.end_updates() 76 | -------------------------------------------------------------------------------- /kuler.py: -------------------------------------------------------------------------------- 1 | import random 2 | 3 | from canvas import * 4 | 5 | def shade_of(color): 6 | r, g, b = color 7 | return r, g, b, random.random() * 0.25 + 0.25 8 | 9 | def gen_color(r, g, b): 10 | return (r/255.0, g/255.0, b/255.0) 11 | 12 | def avg(color): 13 | return float(sum(color) / len(color)) 14 | 15 | class Theme: 16 | 17 | def __init__(self, name, colors): 18 | self.name = name 19 | self.colors = [gen_color(*color) for color in colors] 20 | self.lightest = self.determine_lightest() 21 | self.darkest = self.determine_darkest() 22 | 23 | def determine_lightest(self): 24 | avgs = [(avg(color), color) for color in self.colors] 25 | return max(avgs)[1] 26 | 27 | def determine_darkest(self): 28 | avgs = [(avg(color), color) for color in self.colors] 29 | return min(avgs)[1] 30 | 31 | mucha_winter = Theme( 32 | name='Mucha Winter', 33 | colors=( 34 | (242.0, 212.0, 155.0), 35 | (242.0, 178.0, 102.0), 36 | (191.0, 111.0, 65.0), 37 | (89.0, 18.0, 2.0), 38 | (55.0, 69.0, 65.0), 39 | )) 40 | 41 | mabelis = Theme( 42 | name='Mabelis', 43 | colors=( 44 | (88.0, 0.0, 34.0), 45 | (170.0, 44.0, 48.0), 46 | (255.0, 190.0, 141.0), 47 | (72.0, 123.0, 127.0), 48 | (1.0, 29.0, 36.0), 49 | )) 50 | 51 | full_of_life = Theme( 52 | name='Full of Life', 53 | colors=( 54 | (2.0, 115.0, 115.0), 55 | (3.0, 140.0, 127.0), 56 | (217.0, 179.0, 67.0), 57 | (242.0, 140.0, 58.0), 58 | (191.0, 63.0, 52.0), 59 | )) 60 | 61 | let_the_rays_fall_on_the_earth = Theme( 62 | name='Let the Rays Fall on the Earth', 63 | colors=( 64 | (64.0, 39.0, 104.0), 65 | (127.0, 83.0, 112.0), 66 | (191.0, 117.0, 96.0), 67 | (229.0, 141.0, 0.0), 68 | (255.0, 183.0, 0.0), 69 | )) 70 | 71 | robots_are_cool = Theme( 72 | name='Robots Are Cool', 73 | colors=( 74 | (30.0, 58.0, 64.0), 75 | (104.0, 140.0, 140.0), 76 | (217.0, 209.0, 186.0), 77 | (242.0, 209.0, 148.0), 78 | (242.0, 160.0, 87.0), 79 | )) 80 | 81 | def draw_block(x, y, theme): 82 | start_x, start_y = x, y 83 | for palette_color in theme.colors: 84 | set_fill_color(*palette_color) 85 | fill_rect(start_x, start_y, 25.0, 50.0) 86 | start_x += 25.0 87 | 88 | start_x += 10.0 89 | set_fill_color(*theme.darkest) 90 | fill_rect(start_x, start_y, 25.0, 50.0) 91 | 92 | start_x += 35.0 93 | set_fill_color(*theme.lightest) 94 | fill_rect(start_x, start_y, 25.0, 50.0) 95 | 96 | themes = (mucha_winter, mabelis, full_of_life, let_the_rays_fall_on_the_earth, robots_are_cool) 97 | 98 | if __name__ == 'main': 99 | set_size(1024.0, 1024.0) 100 | 101 | start_x = 10.0 102 | start_y = 10.0 103 | 104 | for theme in themes: 105 | draw_block(start_x, start_y, theme) 106 | start_y += 60.0 107 | -------------------------------------------------------------------------------- /lollipops.py: -------------------------------------------------------------------------------- 1 | import canvas 2 | import random 3 | import math 4 | 5 | from devices import * 6 | from kuler import * 7 | 8 | random.seed() 9 | 10 | width, height = ipad_r_ios7 11 | palette = random.choice(themes) 12 | 13 | canvas.begin_updates() 14 | 15 | canvas.set_size(width, height) 16 | canvas.set_fill_color(*palette.darkest) 17 | canvas.fill_rect(0, 0, width, height) 18 | 19 | canvas.set_fill_color(*random.choice(palette.colors)) 20 | canvas.set_stroke_color(*palette.lightest) 21 | start_x, start_y = (width / 2.0, height / 2.0) 22 | 23 | lollipop_points = [] 24 | 25 | for x in xrange(64): 26 | end_x, end_y = (random.random() * (width * 0.8) + (width * 0.1), random.random() * (height * 0.8) + (height * 0.1)) 27 | lollipop_points.append((end_x, end_y)) 28 | canvas.set_line_width(random.random() * 0.75 + 0.25) 29 | canvas.draw_line(start_x, start_y, end_x, end_y) 30 | 31 | size = random.random() * (width * 0.10) 32 | canvas.fill_ellipse(start_x - (size / 2.0), start_y - (size / 2.0), size, size) 33 | canvas.set_line_width(1.25) 34 | canvas.draw_ellipse(start_x - (size / 2.0), start_y - (size / 2.0), size, size) 35 | 36 | for x in xrange(64): 37 | end_x, end_y = lollipop_points[x] 38 | size = random.random() * (width * 0.10) 39 | canvas.fill_ellipse(end_x - (size / 2.0), end_y - (size / 2.0), size, size) 40 | canvas.set_line_width(1.25) 41 | canvas.draw_ellipse(end_x - (size / 2.0), end_y - (size / 2.0), size, size) 42 | 43 | canvas.end_updates() 44 | -------------------------------------------------------------------------------- /pixelstorm.py: -------------------------------------------------------------------------------- 1 | import canvas 2 | import random 3 | import math 4 | 5 | from devices import * 6 | from kuler import * 7 | 8 | random.seed() 9 | 10 | width, height = ipad_r 11 | palette = random.choice(themes) 12 | 13 | canvas.begin_updates() 14 | 15 | canvas.set_size(width, height) 16 | canvas.set_fill_color(*palette.darkest) 17 | canvas.fill_rect(0, 0, width, height) 18 | 19 | square_size = 32.0 20 | 21 | def fill_square(x, y, size, theme): 22 | canvas.set_fill_color(*shade_of(random.choice(theme.colors))) 23 | canvas.draw_rect(x, y, x + size, y + size) 24 | 25 | def fill_triangles(x, y, size, theme): 26 | # fill upper triangle 27 | canvas.set_fill_color(*shade_of(random.choice(theme.colors))) 28 | canvas.begin_path() 29 | canvas.move_to(x, y) 30 | canvas.add_line(x, y + size) 31 | canvas.add_line(x + size, y + size) 32 | canvas.add_line(x, y) 33 | canvas.fill_path() 34 | 35 | # fill lower triangle 36 | canvas.set_fill_color(*shade_of(random.choice(theme.colors))) 37 | canvas.begin_path() 38 | canvas.move_to(x, y) 39 | canvas.add_line(x + size, y + size) 40 | canvas.add_line(x + size, y) 41 | canvas.add_line(x, y) 42 | canvas.fill_path() 43 | 44 | for gx in xrange(int(width / square_size) + 1): 45 | for gy in xrange(int(height / square_size) + 1): 46 | #func = random.choice((fill_square, fill_triangles, fill_triangles, fill_triangles)) 47 | fill_triangles(gx * square_size, gy * square_size, square_size, palette) 48 | 49 | canvas.end_updates() 50 | -------------------------------------------------------------------------------- /triangles.py: -------------------------------------------------------------------------------- 1 | import canvas 2 | import random 3 | import math 4 | 5 | from devices import * 6 | from kuler import * 7 | 8 | random.seed() 9 | 10 | width, height = iphone_5_ios7 11 | triangle_side = 256.0 12 | palette = random.choice(themes) 13 | 14 | canvas.begin_updates() 15 | 16 | canvas.set_size(width, height) 17 | canvas.set_fill_color(*palette.darkest) 18 | canvas.fill_rect(0, 0, width, height) 19 | 20 | def draw_triangle(x, y, size, num_remaining): 21 | if num_remaining > 0: 22 | canvas.set_fill_color(*shade_of(random.choice(palette.colors))) 23 | canvas.set_stroke_color(*shade_of(random.choice(palette.colors))) 24 | canvas.set_line_width(random.random() * 0.5 + 0.5) 25 | step = math.sqrt(size**2 - (size / 2.0)**2) 26 | canvas.move_to(x - step, y - (size / 2.0)) 27 | canvas.add_line(x, y + size) 28 | canvas.add_line(x + step, y - (size / 2.0)) 29 | canvas.add_line(x - step, y - (size / 2.0)) 30 | canvas.fill_path() 31 | canvas.draw_line(x - step, y - (size / 2.0), x, y + size) 32 | canvas.draw_line(x, y + size, x + step, y - (size / 2.0)) 33 | canvas.draw_line(x + step, y - (size / 2.0), x - step, y - (size / 2.0)) 34 | canvas.draw_line(x, y, x - (step / 2.0), y + (size / 4.0)) 35 | canvas.draw_line(x, y, x + (step / 2.0), y + (size / 4.0)) 36 | canvas.draw_line(x, y, x, y - (size / 2.0)) 37 | canvas.draw_line(x - (step / 2.0), y + (size / 4.0), x + (step / 2.0), y + (size / 4.0)) 38 | canvas.draw_line(x + (step / 2.0), y + (size / 4.0), x, y - (size / 2.0)) 39 | canvas.draw_line(x, y - (size / 2.0), x - (step / 2.0), y + (size / 4.0)) 40 | draw_triangle(random.random() * width, random.random() * height, random.random() * triangle_side, num_remaining - 1) 41 | 42 | x = width / 2.0 43 | y = height / 3.0 # figger 44 | draw_triangle(x, y, triangle_side, 100) 45 | 46 | canvas.end_updates() 47 | -------------------------------------------------------------------------------- /tron_lines.py: -------------------------------------------------------------------------------- 1 | import random 2 | import math 3 | 4 | from canvas import * 5 | from kuler import * 6 | from devices import * 7 | 8 | random.seed() 9 | 10 | def calculate_control_point(radius): 11 | return (4 * radius * (math.sqrt(2) - 1)) / 3 12 | 13 | 14 | def calculate_center_square(width, height): 15 | is_square = is_portrait = is_landscape = False 16 | is_square = width / height == 1 17 | if not is_square: 18 | is_portrait = width / height < 1 19 | if not is_portrait: 20 | is_landscape = True 21 | square_size = min(width, height) / 2.0 22 | if is_square: 23 | offset = (square_size / 2.0, square_size / 2.0) 24 | if is_portrait: 25 | offset = (square_size / 2.0, (height - square_size) / 2.0) 26 | if is_landscape: 27 | offset = ((width - square_size) / 2.0, square_size / 2.0) 28 | return offset[0], offset[1], square_size 29 | 30 | 31 | def draw_circle(x, y, size): 32 | radius = size / 2.0 33 | offset = calculate_control_point(radius) 34 | 35 | point1 = (x + radius, y) 36 | point2 = (x + size, y + radius) 37 | point3 = (x + radius, y + size) 38 | point4 = (x, y + radius) 39 | 40 | main_color = theme.lightest 41 | main_width = random.random() * 4.5 + 0.5 42 | off_color = shade_of(theme.lightest) 43 | off_width = random.random() * 0.75 + 0.5 44 | 45 | off = int(random.random() * 4) 46 | 47 | segment_colors = [main_color, main_color, main_color, main_color] 48 | segment_widths = [main_width, main_width, main_width, main_width] 49 | 50 | segment_colors[off] = off_color 51 | segment_widths[off] = off_width 52 | 53 | # stroke the circle 54 | begin_path() 55 | move_to(*point1) 56 | set_line_width(segment_widths[0]) 57 | set_stroke_color(*segment_colors[0]) 58 | add_curve(point1[0] + offset, point1[1], point2[0], point2[1] - offset, *point2) 59 | draw_path() 60 | begin_path() 61 | move_to(*point2) 62 | set_line_width(segment_widths[1]) 63 | set_stroke_color(*segment_colors[1]) 64 | add_curve(point2[0], point2[1] + offset, point3[0] + offset, point3[1], *point3) 65 | draw_path() 66 | begin_path() 67 | move_to(*point3) 68 | set_line_width(segment_widths[2]) 69 | set_stroke_color(*segment_colors[2]) 70 | add_curve(point3[0] - offset, point3[1], point4[0], point4[1] + offset, *point4) 71 | draw_path() 72 | begin_path() 73 | move_to(*point4) 74 | set_line_width(segment_widths[3]) 75 | set_stroke_color(*segment_colors[3]) 76 | add_curve(point4[0], point4[1] - offset, point1[0] - offset, point1[1], *point1) 77 | draw_path() 78 | 79 | 80 | width, height = ipad_r 81 | grid_x, grid_y, size = calculate_center_square(width, height) 82 | 83 | theme = random.choice(themes) 84 | 85 | set_size(width, height) 86 | 87 | begin_updates() 88 | set_fill_color(*theme.darkest) 89 | fill_rect(0.0, 0.0, width, height) 90 | number_of_circles = 25 91 | for x in xrange(number_of_circles): 92 | step = size / (number_of_circles * 1.0) 93 | step += random.random() * step 94 | draw_circle(grid_x, grid_y, size) 95 | grid_x += step * 0.20 96 | grid_y += step * 0.80 97 | size -= step * 2 98 | end_updates() 99 | 100 | --------------------------------------------------------------------------------