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.
132 lines
4.0 KiB
132 lines
4.0 KiB
#!/usr/bin/env python3 |
|
|
|
import sys |
|
import argparse |
|
import time |
|
import math |
|
import colorsys |
|
import blup.frame |
|
import blup.output |
|
import blup.animation |
|
import blup.writebml |
|
import numpy as np |
|
import random |
|
|
|
WIDTH = 22 |
|
HEIGHT = 16 |
|
DEPTH = 256 |
|
|
|
G = np.array([0, 9.81]) |
|
|
|
class Fireball: |
|
def __init__(self, startpos, startspeed, startcolor, lifetime, t0): |
|
self.startpos, self.startspeed, self.startcolor, self.lifetime = \ |
|
startpos, startspeed, startcolor, lifetime |
|
self.t0 = t0 |
|
self.pos = startpos |
|
self.color = startcolor |
|
self.dead = False |
|
|
|
def update_pos(self, t): |
|
t = t - self.t0 |
|
if t > self.lifetime: |
|
self.dead = True |
|
return |
|
self.pos = 0.5 * G * t**2 + self.startspeed * t + self.startpos |
|
self.color = self.startcolor * (1 - t/self.lifetime) |
|
if random.randint(1, 10) > 8: |
|
self.color = np.array([0, 0, 0]) |
|
|
|
def draw(self, frame): |
|
if not self.dead: |
|
frame.setPixel(int(round(self.pos[0])), int(round(self.pos[1])), |
|
tuple(map(lambda x: int(round(x)), self.color))) |
|
|
|
class Rocket: |
|
def __init__(self, startpos, startspeed, explode_height, t0, color): |
|
self.startpos, self.startspeed, self.explode_height, self.t0 = \ |
|
startpos, startspeed, explode_height, t0 |
|
self.color = color |
|
self.pos = None |
|
self.exploded = False |
|
|
|
def update(self, t): |
|
t = t - self.t0 |
|
if t < 0 or self.exploded: |
|
return |
|
self.pos = 0.5 * G * t**2 + self.startspeed * t + self.startpos |
|
if self.pos[1] <= self.explode_height: |
|
self.exploded = True |
|
self.color = np.array([0, 0, 0]) |
|
|
|
def draw(self, frame): |
|
if self.pos is None or self.exploded: |
|
return |
|
frame.setPixel(int(round(self.pos[0])), int(round(self.pos[1])), |
|
tuple(map(lambda x: int(round(x)), self.color))) |
|
|
|
|
|
|
|
|
|
def getRandomColor(maxval): |
|
return list(map(lambda x: int(round(x*maxval)), colorsys.hsv_to_rgb(random.random(), 1, 1))) |
|
|
|
if __name__ == '__main__': |
|
parser = argparse.ArgumentParser(description='Generate plasma animations') |
|
parser.add_argument('-d', '--delay', type=int, default=50) |
|
parser.add_argument('-n', '--num-rockets', type=int, default=3) |
|
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) |
|
|
|
rockets = [] |
|
for i in range(args.num_rockets): |
|
rockets.append( |
|
Rocket( |
|
np.array([random.randint(0, dim.width-1), dim.height-1]), |
|
np.array([random.randint(-8, 8), -20 + random.randint(-2, 2)]), |
|
4 + random.randint(-2, 2), |
|
random.randint(0, 40) / 10, |
|
np.array([dim.depth-1] * 3) |
|
) |
|
) |
|
|
|
fbs = [] |
|
t = 0 |
|
while True: |
|
frame = blup.animation.AnimationFrame(dim, args.delay) |
|
|
|
for fb in fbs: |
|
fb.update_pos(t) |
|
try: |
|
fb.draw(frame) |
|
except ValueError: |
|
continue |
|
fbs = list(filter(lambda f: not f.dead, fbs)) |
|
|
|
for r in rockets: |
|
r.update(t) |
|
try: |
|
r.draw(frame) |
|
except ValueError: |
|
continue |
|
if r.exploded: |
|
color = np.array(getRandomColor(dim.depth-1)) |
|
for i in range(random.randint(15, 25)): |
|
v = np.array([ |
|
random.choice([-1, 1]) * random.randint(0, 25), |
|
random.choice([-1, 1]) * random.randint(0, 25), |
|
]) |
|
fbs.append(Fireball(r.pos, v, color, 1.5 + random.randint(-1, 1), t)) |
|
rockets = list(filter(lambda r: not r.exploded, rockets)) |
|
|
|
anim.addFrame(frame) |
|
|
|
if len(rockets) == 0 and len(fbs) == 0: |
|
break |
|
t += args.delay / 1000 |
|
|
|
blup.writebml.writeBml(anim, args.output_file)
|
|
|