-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbubbles.py
More file actions
194 lines (136 loc) · 4.9 KB
/
bubbles.py
File metadata and controls
194 lines (136 loc) · 4.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
# -*- coding: utf-8 -*-
"""
Created on Sat Jul 4 16:36:24 2020
This script generates a GIF file which contains an animation
resembling bubbles.
The variables in the Inputs section can
be adjusted to produce a wide range of visual results. The Inputs
section functions as a basic user interface, and only
the Inputs should be needed to operate the script.
The GIF
will automatically be saved to the working directory, so
please be mindful of where that is.
@author: Brian
"""
#%% Setup Environment
from IPython import get_ipython
get_ipython().magic('reset -sf')
import numpy as np
from PIL import Image, ImageDraw
from random import seed, choice, random
#%% Inputs
filename = 'bubbles_5.gif'
# GIF Options
s = 200 # width and height of frame
nframes = 200 # number of frames
# Size/Arrangement Options
seed_number = 1 # seed initialization number
rarity = 6 # rarity parameter (creates a choice sequence with this many 0's and one 1)
r0s = [1] # choice sequence for initial radii
# Grow Options
grow = 2 # choice sequence for growth rate
# Motion Options
mx, my = s/400, s/200 # this sets the motion directory
jit_size = s/100
# Color Options
color_mode = 'random'
color_const = (255,200,170)
# Pop Options
pop_active = 1 # turn popping on/off (1=on, 0=off)
pop_thresh = s/4
#%% Define Functions
""" This function chooses the initial color for the bubbles
in one of two modes: constant or random"""
def choose_color(color_mode):
if color_mode=='constant':
color = color_const # some constant color
elif color_mode=='random':
c_seq = np.arange(150,260,5)
color = (choice(c_seq),choice(c_seq),choice(c_seq))
return color
#%% Make Bubble Class
class bubble:
# Initializer / Instance Attributes
def __init__(self, center, radius, color):
self.center = center
self.radius = radius
self.color = color
def draw(self,im):
cx, cy = self.center[0], self.center[1]
radius = self.radius
x1,x2 = cx-radius, cx+radius
y1,y2 = cy-radius, cy+radius
xy = [x1,y1,x2,y2]
draw = ImageDraw.Draw(im)
draw.ellipse(xy,outline=bubb.color)
def grow(self,grow):
self.radius = self.radius + grow
def jitter(self,jit_size):
cx, cy = self.center[0], self.center[1]
jit_x = choice([-jit_size,0,jit_size])
jit_y = choice([-jit_size,0,jit_size])
self.center = [cx+jit_x, cy+jit_y]
def move(self,mx,my):
cx, cy = self.center[0], self.center[1]
self.center = [cx+mx, cy+my]
def pop(self, popped_list):
fade = 0.6
# If the brightness is low enough we'll consider it totally popped
if self.color[0]<10:
popped_list.append(i-1)
# If the radius is large enough we'll initiate the popping sequence
if self.radius>pop_thresh:
self.radius = self.radius*1.05
self.color = (np.uint8(self.color[0]*fade), np.uint8(self.color[1]*fade), np.uint8(self.color[2]*fade))
return popped_list
#%% Make the images for the GIF
images = []
bubbles = []
seed(seed_number)
pop = 0
# Setup "frames" list (frame numbers)
frames = []
for f in range(nframes):
frames.append(f)
# Setup bubble start choice sequence
bub_chance = [0]*rarity
bub_chance.append(1)
# Create a blank frame
blank = np.zeros([s, s, 3],dtype=np.uint8)
# Make each frame
for f in frames:
im = Image.fromarray(blank)
start = choice(bub_chance)
# Randomly instantiate new bubbles
if start==1:
r0 = choice(r0s)
cx, cy = random()*s, random()*s
color = choose_color(color_mode) # choose random color
new_bubble = bubble([cx,cy],r0,color)
bubbles.append(new_bubble)
# Draw each bubble and update their attributes
popped_list = []
for i, bubb in enumerate(bubbles, 1):
# Draw the bubble
bubb.draw(im)
# Grow the bubble for the next frame
bubb.grow(grow)
# Jitter the bubble for the next frame
bubb.jitter(jit_size)
# Move the bubble for the next frame
bubb.move(mx,my)
# Pop the bubble stuff
if pop_active==1:
popped_list = bubb.pop(popped_list)
# Pop the bubble stuff
if len(popped_list)>0:
for i in popped_list: del bubbles[i]
images.append(im)
#%% Save as GIF
images[0].save(filename,
save_all=True,
append_images=images[1:],
optimize=False,
duration=1000/24,
loop=0)
print('DONE')