#!/usr/bin/env python3 import sys import random import argparse import blup.frame import blup.output import blup.animation import blup.writebml import colorsys WIDTH = 22 HEIGHT = 16 DEPTH = 256 def convert_color(c): return list(map(lambda x: int(round(x*(DEPTH-1))), c)) def get_random_color(): return colorsys.hsv_to_rgb(random.random(), 1, 1) def get_random_point(): return (random.randint(0, WIDTH-1), random.randint(0, HEIGHT-1)) def cap(x): return min(1, max(0, x)) def cyc(x): while x < 0: x += 1 while x > 1: x -= 1 return x class Point: def __init__(self, pos, color, evolve): self.pos = pos self.color = color self.neighbours = [] h, s, v = colorsys.rgb_to_hsv(*color) self.evolve = evolve if 'h' in evolve: h += (random.random()-.5) * 0.1 if 's' in evolve: s += (random.random()-.5) * 0.5 if 'v' in evolve: v += (random.random()-.5) * 0.5 self.ncolor = colorsys.hsv_to_rgb(cyc(h), cap(s), cap(v)) def __eq__(self, other): return self.pos == other.pos def __hash__(self): return self.pos.__hash__() def get_neighbours(self): for x in [-1, 0, 1]: for y in [-1, 0, 1]: n = (self.pos[0]+x, self.pos[1]+y) if n[0] >= 0 and n[1] >= 0 and n[0] < WIDTH and \ n[1] < HEIGHT and abs(x+y) < 2: yield Point(n, self.ncolor, self.evolve) class Blob: def __init__(self, pos, color): e = random.choice('hsv') if random.random() > 0.8: e += random.choice('hsv') p = Point(pos, color, e) self.points = set([p]) self.candids = set(p.get_neighbours()) self.completed = False def grow(self): if len(self.candids) == 0: self.completed = True return newp = random.sample(self.candids, 1)[0] self.candids.remove(newp) self.points.add(newp) self.candids = self.candids.union(set(newp.get_neighbours()) - self.points - self.candids) def draw(self, frame): for p in self.points: frame.setPixel(p.pos[0], p.pos[1], convert_color(p.color)) if __name__ == '__main__': parser = argparse.ArgumentParser(description='Generate blob animations') parser.add_argument('-d', '--delay', type=int, default=50) parser.add_argument('-t', '--time', type=int, default=15) parser.add_argument('output_file') args = parser.parse_args() dim = blup.frame.FrameDimension(WIDTH, HEIGHT, DEPTH, 3) anim = blup.animation.Animation(dim) anim.tags['description'] = ' '.join(sys.argv) t = 0 blobs = [Blob(get_random_point(), get_random_color())] while t < args.time: t += args.delay / 1000 frame = blup.animation.AnimationFrame(dim, args.delay) for b in blobs: for i in range(4): b.grow() b.draw(frame) if len(blobs[-1].points) > WIDTH*HEIGHT*0.6 and len(blobs) < 3: blobs.append(Blob(get_random_point(), get_random_color())) if len(blobs) >=2 and blobs[0].completed and blobs[1].completed: blobs.remove(blobs[0]) anim.addFrame(frame) blup.writebml.writeBml(anim, args.output_file)