You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

121 lines
3.4 KiB

#!/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)