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.

133 lines
3.9 KiB

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