Last active
May 25, 2017 06:05
-
-
Save aman-tiwari/a7d1078ac0ea6e039a788bb1f3e3e78a to your computer and use it in GitHub Desktop.
A little particle system for your terminal : )
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from itertools import chain | |
from math import sqrt | |
from random import random | |
import drawille | |
def wrap(x, low, high): | |
if x > high: | |
return low | |
elif x < low: | |
return high | |
return x | |
class Particle(object): | |
__slots__ = ['x', 'y', 'x_velocity', 'y_velocity'] | |
def __init__(self, x, y, x_velocity, y_velocity): | |
self.x = x | |
self.y = y | |
self.x_velocity = x_velocity | |
self.y_velocity = y_velocity | |
def make_particle(x, y, x_velocity, y_velocity): | |
return Particle(x, y, x_velocity, y_velocity) | |
def particle_system(width, height, | |
n_particles, | |
infulence_distance, | |
attract, | |
repel, | |
repel_distance, | |
steer): | |
drag = 0.04 | |
# x, y, x_velocity, y_velocity | |
particles = [make_particle(random() * width, random() * height, 0.0, 0.0) | |
for _ in range(n_particles)] | |
prev_positions = [[], [], [], []] | |
while True: | |
for particle in particles: | |
for other in particles: | |
if particle != other: | |
dx = other.x - particle.x | |
dy = other.y - particle.y | |
distance = sqrt((dx * dx) + (dy * dy)) | |
if distance < infulence_distance: | |
accel_x = 0.0 | |
accel_y = 0.0 | |
accel_x += dx * attract | |
accel_y += dy * attract | |
if distance < repel_distance: | |
inverse_dist = (repel_distance / | |
(distance + 0.1)) ** 2 | |
accel_x += dx * inverse_dist * repel | |
accel_y += dy * inverse_dist * repel | |
accel_x += (other.x_velocity - | |
particle.x_velocity) * steer | |
accel_y += (other.y_velocity - | |
particle.y_velocity) * steer | |
particle.x_velocity += accel_x | |
particle.y_velocity += accel_y | |
particle.x_velocity *= 1.0 - drag | |
particle.y_velocity *= 1.0 - drag | |
particle.x += particle.x_velocity | |
particle.y += particle.y_velocity | |
particle.x = wrap(particle.x, 0, width) | |
particle.y = wrap(particle.y, 0, height) | |
positions = [] | |
# x y size inversely related to x y velocity | |
for particle in particles: | |
scale_x = max(1, min(10, int(4.0 / particle.x_velocity))) | |
scale_y = min(10, int(4.0 / particle.y_velocity)) | |
for x_offset in range(scale_x): | |
for y_offset in range(scale_y): | |
positions.append( | |
(particle.x + x_offset, particle.y + y_offset)) | |
positions.append((particle.x, particle.y)) | |
positions.append((width + 10, height + 10)) | |
positions.append((0, 0)) | |
prev_positions = prev_positions[1:] | |
prev_positions.append(positions) | |
yield chain( # drawille.line(0, 0, width - 1, 0), | |
#drawille.line(width - 1, 0, width - 1, height - 1), | |
#drawille.line(0, 0, 0, height - 1), | |
#drawille.line(0, height - 1, width - 1, height - 1), | |
*prev_positions) | |
canvas = drawille.Canvas() | |
width, height = drawille.getTerminalSize() | |
print width, height | |
# if you get _curses.error: addstr() returned ERR lower the width & height | |
# multipliers | |
drawille.animate(canvas, particle_system, 1. / 24, width * 2.0 - 10, height * 3.0 - 10, | |
120, 150, 0.001, -0.02, 30, 0.1) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
you might need to change the numbers width and height are multiplied by to get it to fill up your terminal or if you get
_curses.error: addstr() returned ERR
or you can make your terminal bigger