manring.py

download raw

# /// script
# requires-python = ">=3.14"
# dependencies = [
#     "colour",
#     "numpy",
#     "py5",
# ]
# ///

from dataclasses import dataclass
from colour import Color
import py5
import numpy as np
import random

maxit = 64
num = 500
dt = 10
factor = 640
ox = -.75

@dataclass
class Lisa:
    A: float
    B: float
    alpha: float
    beta: float
    delta: float

    def __call__(self, t):
        return self.A * np.sin(self.alpha * t + self.delta) + self.B * 1j * np.sin(self.beta * t)

l = Lisa(
        alpha = random.uniform(0, 1),
        beta = random.uniform(0, 1),
        delta = random.uniform(0, np.pi),
        A = py5.width,
        B = py5.height)


def random_uniform(top):
    return random.uniform(0, top)


def setup():
    py5.full_screen()
    py5.frame_rate(30)
    py5.background(0)

ot = 0
def draw():

    rx = py5.width
    ry = py5.height 

    py5.blend_mode(py5.SUBTRACT)
    py5.fill(4, 4, 4)
    py5.rect(0, 0, rx, ry)

    alpha = 16
    global ot
    t = (py5.millis() + random.random() * 16) * .001
    tt = np.linspace(ot, t, num=num, dtype=np.float32)
    ot = t
    l.A = 1
    l.B = py5.height / py5.width
    coords = l(tt) + ox
    xi = coords
    xi = xi
    c = xi[:]

    py5.blend_mode(py5.BLEND)
    py5.stroke_weight(3)
    with py5.begin_shape(py5.POINTS):
        for it in range(maxit):
            py5.stroke(Color(hue=(t * .1 + it / maxit) % 1, saturation=1, luminance=.5), alpha)
            pts = (xi - ox) * factor + (rx + 1j * ry) * 0.5
            pts = np.stack([np.real(pts), np.imag(pts)], axis=1)
            py5.vertices(pts)
            xi = xi * xi + c

def mouse_pressed():
    global l
    l = Lisa(
            alpha = random.uniform(0, 1),
            beta = random.uniform(0, 1),
            delta = random.uniform(0, np.pi),
            A = py5.width,
            B = py5.height)


py5.run_sketch()