sketch.py
# -*- coding: utf-8 -*-
import random
import q5
import numpy as np
import GPy
N = 200
colors = [
(0, 220, 240), (240, 100, 0)
]
def choice_color():
return colors[0] if random.random() > 0.05 else colors[1]
class Slime:
def __init__(self):
self.x = np.linspace(0, 2 * np.pi, N)
self.y = np.zeros((1, N))
self.period = 1.0
self.r_wave = 80.0
self.r_body = 250.0
self.eye_size = 100.0
self.eye_pos_l = q5.Vector(-100.0, 0.0)
self.eye_pos_r = q5.Vector(100.0, 0.0)
self.eye_basis = (0, N // 2)
self.color = choice_color()
def set_y(self, y):
self.y = y
l = random.randint(0, N // 2) + N // 4
r = random.randint(0, N // 2 - 1)
r = r if r <= N // 4 else r + N // 2
assert N // 4 <= l <= N // 4 * 3, l
assert 0 <= r <= N // 4 or N // 4 * 3 <= r < N, r
self.eye_basis = (l, r)
def draw(self, elapsed_time):
t = elapsed_time * np.pi * 2.0 / self.period
r1 = self.r_wave * min(1.0, 1.5 * np.sin(t) ** 4.0)
r2 = self.r_body + r1 * self.y
px = r2 * np.cos(self.x)
py = r2 * np.sin(self.x)
pts = np.vstack([px, py]).T
eye_diff_l = q5.Vector(*pts[self.eye_basis[0]])
eye_diff_r = q5.Vector(*pts[self.eye_basis[1]])
eye_diff_l = eye_diff_l - eye_diff_l.normalize().mult(self.r_body)
eye_diff_r = eye_diff_r - eye_diff_r.normalize().mult(self.r_body)
eye_pos_l = self.eye_pos_l + eye_diff_l.mult(0.25)
eye_pos_r = self.eye_pos_r + eye_diff_r.mult(0.25)
q5.push_matrix()
q5.fill(*self.color)
q5.polygon(pts)
q5.push_matrix()
q5.translate(eye_pos_l.x, eye_pos_l.y)
q5.fill(240)
q5.circle(0.0, 0.0, self.eye_size)
q5.fill(20)
q5.circle(0.0, 0.0, self.eye_size / 2.0)
q5.pop_matrix()
q5.push_matrix()
q5.translate(eye_pos_r.x, eye_pos_r.y)
q5.fill(240)
q5.circle(0.0, 0.0, self.eye_size)
q5.fill(20)
q5.circle(0.0, 0.0, self.eye_size / 2.0)
q5.pop_matrix()
q5.pop_matrix()
class App(q5.BaseApp):
def setup(self):
q5.title('sketch_220220b')
q5.full_screen(True)
# q5.loop_ntimes(60 * 60)
N = 200
self.period = 1.0
self.n_rows = 3
self.n_cols = 5
self.n_samples = self.n_rows * self.n_cols
self.cell_scale = 1.0 / min(self.n_rows, self.n_cols)
self.x = np.linspace(0, 2 * np.pi, N)
self.y = np.zeros((self.n_samples, N))
kernel = GPy.kern.src.periodic.PeriodicExponential(
input_dim=1, variance=1.0, lengthscale=0.05, period=np.pi*2.0
)
# Mean function
self.mu = np.zeros(N)
# Cov function
self.cov = kernel.K(self.x[:, np.newaxis],
self.x[:, np.newaxis])
self.slime_grid = []
for i in range(self.n_rows):
row = []
for j in range(self.n_cols):
row.append(Slime())
self.slime_grid.append(row)
self.elapsed_time = 0.0
def update(self):
if self.elapsed_time >= self.period / 2.0:
self.y = np.random.multivariate_normal(
self.mu, self.cov, size=self.n_samples
)
for i in range(self.n_rows):
for j in range(self.n_cols):
self.slime_grid[i][j].set_y(self.y[i*self.n_cols+j, :])
self.elapsed_time = 0.0
self.elapsed_time += 1.0 / 60.0
def draw(self):
q5.background(220)
for i in range(self.n_rows):
for j in range(self.n_cols):
q5.push_matrix()
dj = 0.5 if self.n_cols % 2 == 0 else 0.0
di = 0.5 if self.n_rows % 2 == 0 else 0.0
q5.translate(
(j - self.n_cols // 2.0 + dj) * q5.width / self.n_cols,
(i - self.n_rows // 2.0 + di) * q5.height / self.n_rows
)
q5.scale(self.cell_scale, self.cell_scale)
q5.stroke_weight(3.0 * min(self.n_cols, self.n_rows))
self.slime_grid[i][j].draw(self.elapsed_time)
q5.pop_matrix()
# q5.save_frame('frames/{0:05d}.png'.format(q5.frame_count))
if __name__ == '__main__':
app = App()
app.run()