#!/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(): if random.random() < 0.5: s = 1 v = random.random() else: s = random.random() v = 1 return colorsys.hsv_to_rgb(random.random(), s, v) class Unrath: def __init__(self, world): self.world = world self.shape = set([(0, 0)]) shapesize = random.randint(2, 5) while len(self.shape) < shapesize: p = random.sample(self.shape, 1)[0] self.shape.add((p[0]+random.randint(-1, 1), p[1]+random.randint(-1, 1))) minx = min(map(lambda p: p[0], self.shape)) miny = min(map(lambda p: p[1], self.shape)) self.shape = {(p[0]+abs(minx), p[1]+abs(miny)) for p in self.shape} self.shapewidth = max(map(lambda p: p[0], self.shape)) shapeheight = max(map(lambda p: p[1], self.shape)) y = random.randint(0, HEIGHT-shapeheight) if random.random() > 0.5: d = 1 x = -self.shapewidth else: d = -1 x = WIDTH + self.shapewidth self.pos = (x, y) self.finished = False self.speed = d * random.randint(2, WIDTH/2) self.color = get_random_color() def update(self, dt, nocheck=False): if (self.pos[0] + self.shapewidth < 0 and self.speed < 0) or \ (self.pos[0] > WIDTH and self.speed > 0): self.finished = True return newpos = (self.pos[0] + dt*self.speed, self.pos[1]) newpoints = self.get_points(newpos) collision = False for unrath in self.world.unraethe - {self}: if len(unrath.get_points().intersection(newpoints)) > 0: collision = True if abs(unrath.speed) > abs(self.speed): fast = unrath slow = self else: slow = unrath fast = self slow.speed = fast.speed * (1.1 + random.random()/10) slow.update(dt, True) if not collision: self.pos = newpos def get_points(self, pos=None): if pos is None: pos = self.pos return {(int(pos[0] + s[0]), int(pos[1] + s[1])) for s in self.shape} def draw(self, frame): for p in self.get_points(): try: frame.setPixel(p[0], p[1], convert_color(self.color)) except ValueError: pass class World: def __init__(self, num_unraethe): self.num_unraethe = num_unraethe self.unraethe = {} def update(self, dt): self.unraethe = set(filter(lambda u: not u.finished, self.unraethe)) if len(self.unraethe) < self.num_unraethe: self.unraethe.add(Unrath(self)) for u in self.unraethe: u.update(dt) def draw(self, frame): for u in self.unraethe: u.draw(frame) if __name__ == '__main__': parser = argparse.ArgumentParser(description='Generate Unrath animations') parser.add_argument('-d', '--delay', type=int, default=50) parser.add_argument('-t', '--time', type=int, default=15) parser.add_argument('-n', '--num-unraethe', type=int, default=5) 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 w = World(args.num_unraethe) while t < args.time: t += args.delay / 1000 frame = blup.animation.AnimationFrame(dim, args.delay) w.update(args.delay / 1000) w.draw(frame) anim.addFrame(frame) blup.writebml.writeBml(anim, args.output_file)