#!/usr/bin/env python3 import sys import random import math import argparse import collections import blup.frame import blup.output import blup.animation import blup.writebml import colorsys WIDTH = 22 HEIGHT = 16 DEPTH = 256 class Point(collections.namedtuple('Point', ['x', 'y'])): def __add__(self, other): return Point(self.x + other.x, self.y + other.y) def __sub__(self, other): return Point(self.x - other.x, self.y - other.y) def __mul__(self, other): if isinstance(other, Point): raise Exception('not implemented') else: return Point(self.x * other, self.y * other) def __truediv__(self, other): if isinstance(other, Point): raise ValueError() else: return self * (1/other) @property def len(self): return math.sqrt(self.x**2 + self.y**2) @property def n(self): n = Point(self.y, -self.x) return n / n.len @property def intp(self): return Point(int(round(self.x)), int(round(self.y))) 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(), 0.5 + random.random() / 2, 1) class Line: def __init__(self, size): self.size = size r = random.choice([0, 1]) s = random.choice([-1, 1]) if r == 0: self.pos = Point(size.x if s == -1 else 0, random.randint(0, size.y - 1)) else: self.pos = Point(random.randint(0, size.x - 1), size.y if s == -1 else 0) self.dir = Point(s if r == 0 else 0, s if r == 1 else 0) m = max(size.x, size.y) self.length = random.randint(int(0.4 * m), int(1.1 * m)) self.color = get_random_color() self.speed = 10 self.done = False def update(self, t, dt): self.pos += self.dir * (dt * self.speed) end = self.pos - self.dir * self.length if self.dir.x > 0 and end.x > self.size.x \ or self.dir.y > 0 and end.y > self.size.y \ or self.dir.x < 0 and end.x < 0 \ or self.dir.y < 0 and end.y < 0: self.done = True def draw(self, frame): if self.done: return for i in range(self.length): p = self.pos.intp - self.dir * i try: frame.setPixel(p.x, p.y, convert_color(self.color)) except ValueError: pass if __name__ == '__main__': parser = argparse.ArgumentParser(description='Generate 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) lines = [] t = 0 dt = args.delay / 1000 while t < args.time or len(lines) > 0: t += dt frame = blup.animation.AnimationFrame(dim, args.delay) if len(lines) < 5 and t < args.time: lines.append(Line(Point(WIDTH, HEIGHT))) for l in lines: l.update(t, dt) l.draw(frame) lines = list(filter(lambda l: not l.done, lines)) anim.addFrame(frame) blup.writebml.writeBml(anim, args.output_file)