sketch_220220a

sketch.py

# -*- coding: utf-8 -*-
import math
import random
from typing import List

import q5
from matplotlib import colors as mc

N = 200
palette = [
    (245, 93, 116),
    (69, 97, 244),
    (245, 196, 44),
    (56, 245, 94),
]


def set_saturation(color, s):
    # s in [0.0, 1.0]
    color_rgb = tuple(map(lambda x: x / 255, color))
    color_hsv = mc.rgb_to_hsv(color_rgb)
    color_hsv[1] = s
    color_rgb_mod = mc.hsv_to_rgb(color_hsv)
    return tuple(map(lambda x: int(x * 255), color_rgb_mod))


class Shape:
    def __init__(self, a=64.0, b=300.0,
                 rot_speed=12.0, spike_freq=8.0, color=(255, 255, 255)):
        self.a = a
        self.b = b
        self.rot_speed = rot_speed
        self.spike_freq = spike_freq
        self.color = color

    def draw(self):
        t = q5.frame_count / 60.0
        pts = []
        spike = math.pow(math.sin(t * 1.0), self.spike_freq * 2.0)
        for k in range(N):
            p = k / N * math.pi * 2.0
            r1 = self.a * spike
            r2 = self.b + r1 * math.sin(p * 10.0 - t * self.rot_speed)
            x = r2 * math.cos(p)
            y = r2 * math.sin(p)
            pts.append((x, y))

        c = set_saturation(self.color, min(0.8, spike))
        q5.fill(*c)
        q5.polygon(pts)


class App(q5.BaseApp):
    def setup(self):
        q5.title('2/1 #AltEdu2022')
        # q5.set_loop_count(600)

        self.nrows = random.randint(2, 7)
        self.ncols = self.nrows

        self.shape_grid = []
        for i in range(self.nrows):
            row = []
            for j in range(self.ncols):
                row.append(
                    Shape(
                        a=32.0*random.randint(1, 4),
                        b=200.0,
                        rot_speed=random.uniform(-20.0, 20.0),
                        spike_freq=random.randint(2, 10),
                        color=random.choice(palette)
                    )
                )
            self.shape_grid.append(row)

    def update(self):
        pass

    def draw(self):
        q5.background(220)
        q5.stroke_weight(2.0)
        for i, row in enumerate(self.shape_grid):
            for j, shape in enumerate(row):
                q5.push_matrix()

                dj = 0.5 if self.ncols % 2 == 0 else 0.0
                di = 0.5 if self.nrows % 2 == 0 else 0.0
                q5.translate(
                    (j - self.ncols // 2 + dj) * q5.width / self.ncols,
                    (i - self.nrows // 2 + di) * q5.height / self.nrows
                )
                q5.scale(1.0 / self.ncols, 1.0 / self.nrows)
                q5.stroke_weight(5.0 * self.ncols)
                shape.draw()

                q5.pop_matrix()

        # t = q5.frame_count
        # q5.save_frame(f'frames/{t:05d}.png')


if __name__ == '__main__':
    app = App()
    app.run()