#!/usr/bin/python3 # -*- coding: utf-8 -*- # -*- mode: Python -*- ''' v0.1.0 Licensed under GNU GPLv3 by cocoa ''' from __future__ import print_function import math import random import sys import os import time import redis import ast import argparse MAX_PARTICLES = 50 MAX_TIME = 500 argsparser = argparse.ArgumentParser(description="Dummy generator") argsparser.add_argument("-f","--fps",help="Frame Per Second",default=30,type=int) argsparser.add_argument("-v","--verbose",action="store_true",help="Verbose output") # Redis Args argsparser.add_argument("-i","--ip",help="IP address of the Redis server ",default="127.0.0.1",type=str) argsparser.add_argument("-p","--port",help="Port of the Redis server ",default="6379",type=str) # argsparser.add_argument("-M","--max-particles",help="Max Particles. Default:{}".format(MAX_PARTICLES),default=MAX_PARTICLES,type=int) argsparser.add_argument("-m","--max-time",help="Max Particles. Default:{}".format(MAX_TIME),default=MAX_TIME,type=int) args = argsparser.parse_args() verbose = args.verbose ip = args.ip port = args.port max_particles = args.max_particles max_time = args.max_time def debug(*args, **kwargs): if( verbose == False ): return print(*args, file=sys.stderr, **kwargs) def rgb2int(rgb): #debug(name,"::rgb2int rbg:{}".format(rgb)) return int('0x%02x%02x%02x' % tuple(rgb),0) def spectrum_120( ): return ast.literal_eval(redisData["spectrum_10"]) def rgb2int(rgb): #debug(name,"::rgb2int rbg:{}".format(rgb)) return int('0x%02x%02x%02x' % tuple(rgb),0) def msNow(): return time.time() def refreshRedis(): global redisData for key in redisKeys: redisData[key] = ast.literal_eval(r.get(key).decode('ascii')) name="generator::redilisys_particles" class UnpreparedParticle(Exception): pass class Particle(object): def __init__(self, x, y, m): self.x = x self.y = y self.m = m self.dx = 0 self.dy = 0 self.connectedTo = [] self.decay = random.randint(10,max_time) self.color = (random.randint(128,256) - int(12.8 * self.m), random.randint(128,256) - int(12.8 * self.m), random.randint(128,256) - int(12.8 * self.m)) self.color = (255,255,255) #debug( self.color ) def interact(self, bodies): self.connectedTo = [] spec = redisData["spectrum_10"] power = int(sum(spec[4:6])) for other in bodies: if other is self: continue dx = other.x - self.x dy = other.y - self.y dist = math.sqrt(dx*dx + dy*dy) if dist == 0: dist = 1 if dist < 100 and random.randint(0,power) > 0.5 : self.connectedTo.append(other) self.decay += 2 factor = other.m / dist**2 high_power = sum(spec[8:9]) if sum(spec[8:9]) != 0 else 0.01 self.dx += (dx * factor * self.m) self.dy += (dy * factor * self.m) #print "factor %f" % (factor,) def move(self): spec = redisData["spectrum_10"] x_friction = (2.2-(1+spec[7]/2)) y_friction = (2.2-(1+spec[7]/2)) #x_friction = 1.02 #y_friction = 1.04 self.dx /= x_friction if x_friction != 0 else 0.01 self.dy /= y_friction if y_friction != 0 else 0.01 self.x += self.dx self.y += self.dy if self.x > max_width: self.dx = - self.dx /8 self.x = max_width if self.x < 1: self.dx = - self.dx /8 self.x = 1 if self.y > max_height: self.dy = - self.dy /4 self.y = max_height if self.y < 1: self.dy = - self.dy /4 self.y = 1 #print "(%.2f,%.2f) -> (%.2f,%.2f)" % (ox, oy, self.x, self.y) def attractor(self,attractor): spec = redisData["spectrum_10"] power = sum(spec[0:4])/3 # If we're going in the direction of center, reverse next_x = self.x + self.dx next_y = self.y + self.dy next_dx = attractor["x"] - self.x next_dy = attractor["y"] - self.y next_dist = math.sqrt(next_dx*next_dx + next_dy*next_dy) dx = attractor["x"] - self.x dy = attractor["y"] - self.y dist = math.sqrt(dx*dx + dy*dy) if dist == 0: dist = 1 factor = power/ dist**2 x_acceleration = (dx * factor * power * power) y_acceleration = (dx * factor * power * power) if next_dist > dist: self.dx -= x_acceleration * power self.dy -= y_acceleration * power else: self.dx += x_acceleration self.dy += y_acceleration class Attractor(Particle): def move(self): pass class ParticleViewer(object): def __init__(self, particles, size=(800,800)): (self.width, self.height) = size self.size = size self.particles = particles self.xoff = 0 self.yoff = 0 self.scalefactor = 1 def redraw(self): pl = [] drawnVectors = [] for p in self.particles: x = int(self.scalefactor * p.x) - self.xoff y = int(self.scalefactor * p.y) - self.yoff if x > max_width: x = max_width if x < 1: x = 1 if y > max_height: y = max_height if y < 1: y = 1 color = rgb2int(p.color) pl.append([x+1,y+1,0]) pl.append([x+1,y+1,color]) pl.append([x,y,color]) for other in p.connectedTo: if [other,self] in drawnVectors: continue drawnVectors.append([other,self]) pl.append([x,y,0]) pl.append([x,y,color]) pl.append([other.x,other.y,color]) print(pl,flush = True) def decayParticles(self): for i,p in enumerate(self.particles): # Handle positional decay if p.decay == 0: del self.particles[i] continue p.decay = p.decay - 1 # Handle color decay n = int(255 * (p.decay / max_time )) p.color = (n,n,n) def emitParticles(self): spec = redisData["spectrum_10"] power = sum(spec[6:]) if len(self.particles ) > math.sqrt(max_particles): if len(self.particles) > max_particles: return if random.random() > power: return # x is either left or right d = 600 rx = 100 if random.randint(0,1) else 700 #rx = random.randint(1,max_width) ry = random.randint(1,max_height) spec = redisData["spectrum_10"] m = random.randint(1,1+int(10*spec[7])) particles.append(Particle(rx, ry, m)) def tick(self): self.decayParticles() self.emitParticles() for p in self.particles: p.interact(self.particles) p.attractor({ "x":max_width/2, "y":max_height/2 }) for p in particles: p.move() self.redraw() def scale(self, factor): self.scalefactor += factor max_width = 800 max_height = 800 redisKeys = ["spectrum_120","spectrum_10"] redisData = {} redisLastHit = msNow() - 99999 r = redis.Redis( host=ip, port=port) white = 16777215 refreshRedis() if __name__ == "__main__": particles = [] # particles.append(Attractor(320, 200, 10)) # particles.append(Attractor(100, 100, 10)) win = ParticleViewer(particles) try: while True: win.tick() refreshRedis() time.sleep(.03) except KeyboardInterrupt: pass