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.

122 lines
3.6 KiB

#!/usr/bin/env python3
import sys
import random
import numpy as np
import argparse
import blup.frame
import blup.output
import blup.animation
import blup.writebml
import colorsys
WIDTH = 22
HEIGHT = 16
DEPTH = 256
def fill_trace(points):
for i in range(len(points)):
yield points[i]
if i == len(points)-1:
break
v = points[i+1] - points[i]
l = int(np.linalg.norm(v))
for j in range(l):
yield points[i] + v * (j+1)/(l+1)
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)
class Orb:
def __init__(self, pos, speed, tracelen, color, tracecolor, boxsize):
self.pos = pos
self.speed = speed
self.tracelen = tracelen
self.color = color
self.tracecolor = tracecolor
self.boxsize = boxsize
self.trace = []
def update(self, dt):
newpos = self.pos + self.speed * dt
#newpos = self.pos
for dim in [0, 1]:
if newpos[dim] >= self.boxsize[dim] or newpos[dim] <= 0:
newpos[dim] = 0 if newpos[dim]<0 else self.boxsize[dim]-1
self.speed[dim] *= -1
self.speed += np.array([random.randint(-5, 6), random.randint(-5, 6)])
self.trace.insert(0, self.pos)
self.trace = self.trace[:self.tracelen]
self.pos = newpos
def draw(self, frame):
for i, p in enumerate(fill_trace([self.pos] + self.trace)):
f = (self.tracelen - i) / self.tracelen
try:
c = colorsys.rgb_to_hsv(*self.tracecolor)
s = 0.1 if random.random()>0.9 else c[1]
c = colorsys.hsv_to_rgb(c[0], s, c[2]*f)
frame.setPixel(int(p[0]), int(p[1]), convert_color(c))
except ValueError:
pass
offs = [ np.array([x,y]) for x in [-1,0,1] for y in [-1,0,1] ]
points = []
for o in offs:
p = self.pos.astype('int') + o
if random.random() > 0.2 and not (p == np.array([0,0])).all():
points.append(p)
for p in points:
try:
c = colorsys.rgb_to_hsv(*self.color)
c = colorsys.hsv_to_rgb(c[0], c[1], c[2]*0.2)
frame.setPixel(p[0], p[1], convert_color(c))
except ValueError:
pass
frame.setPixel(int(self.pos[0]), int(self.pos[1]), convert_color(self.color))
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Generate plasma animations')
parser.add_argument('-d', '--delay', type=int, default=50)
parser.add_argument('-t', '--time', type=int, default=15)
parser.add_argument('-n', '--num-orbs', type=int, default=2)
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)
orbs = []
for i in range(args.num_orbs):
orbs.append(Orb(
np.array([random.randint(0, WIDTH-1),random.randint(0, HEIGHT-1)]),
np.array([8,10]),
20,
get_random_color(),
get_random_color(),
np.array([WIDTH, HEIGHT])
))
t = 0
while t < args.time:
t += args.delay / 1000
frame = blup.animation.AnimationFrame(dim, args.delay)
for orb in orbs:
orb.update(args.delay / 1000)
orb.draw(frame)
anim.addFrame(frame)
blup.writebml.writeBml(anim, args.output_file)