From 8a6de3f4ecf41051475b1f64ca1ec05897014490 Mon Sep 17 00:00:00 2001 From: alban Date: Sun, 29 Nov 2020 07:59:39 +0100 Subject: [PATCH] [fix] cleaning up --- generators/dummy.py | 6 +- generators/particles_example.py | 185 ++++++++++++++++++++++++++++++++ lib/clitools.py | 5 +- 3 files changed, 190 insertions(+), 6 deletions(-) create mode 100755 generators/particles_example.py diff --git a/generators/dummy.py b/generators/dummy.py index 725e9bd..497dd26 100755 --- a/generators/dummy.py +++ b/generators/dummy.py @@ -21,10 +21,6 @@ from os import path, getcwd abspath, filename = path.split(path.realpath(__file__ )) sys.path.insert(0, path.join(abspath,"../lib")) from clitools import Clitools - -name="generator::dummy" - - import argparse argsparser = argparse.ArgumentParser(description="dummy generator") @@ -38,7 +34,7 @@ verbose=args.verbose cli = Clitools({ "verbose" : verbose, "looptime" : 1 / fps, - "name" : name + "name" : "generator::dummy" }) diff --git a/generators/particles_example.py b/generators/particles_example.py new file mode 100755 index 0000000..c98564c --- /dev/null +++ b/generators/particles_example.py @@ -0,0 +1,185 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# -*- mode: Python -*- + + +''' + +v0.1.0 + +An example particle system reproducing some kind of flock simulation + +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 + +from os import path, getcwd +abspath, filename = path.split(path.realpath(__file__ )) +sys.path.insert(0, path.join(abspath,"../lib")) +from clitools import Clitools + + +MAX_WIDTH = 800 +MIN_WIDTH = 0 +MAX_HEIGHT = 800 +MIN_HEIGHT = 0 +MAX_SPEED = 10 +WHITE = 16777215 + + +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") +argsparser.add_argument("-n","--number",help="Particule Number",default=50,type=int) + + +args = argsparser.parse_args() +verbose = args.verbose +fps = args.fps +patricle_number = args.number +scene_width = MAX_WIDTH - MIN_WIDTH +scene_height = MAX_HEIGHT - MIN_HEIGHT +center_x = MIN_WIDTH + scene_width / 2 +center_y = MIN_HEIGHT + scene_height / 2 + +cli = Clitools({ + "verbose" : verbose, + "looptime" : 1 / fps, + "name" : "generator::particles_example" + }) + + +class Particle(object): + + def __init__(self, x = 0, y = 0, color = 0, dx = 0, dy = 0): + self.x = x + self.y = y + self.color = color + # Store speed in 2 dimensions + self.dx = dx + self.dy = dy + + def interact(self, bodies): + """ + Computes particles interactions + This is a good place to calculate distance between particles for example + """ + for other in bodies: + if other is self: + continue + + # For example, we average our speed with the other particle + dist_x = other.x - self.x + dist_y = other.y - self.y + dist = math.sqrt(dist_x*dist_x + dist_y*dist_y) + if dist == 0 : + dist = 1 + if dist > 50 : + continue + if dist > 5 : + factor = math.sqrt(50-dist) -1 + if factor > 1: + factor = 1 + self.dx = 0.5*self.dx + 0.5*((1 -factor)*self.dx + factor*other.dx) + (random.random() - 0.5) * 2 + self.dy = 0.5*self.dy + 0.5*((1 -factor)*self.dy + factor*other.dy) + (random.random() - 0.5) * 2 + else: + # Too close: avoid + self.dx += random.random() + self.dy += random.random() + + def move(self): + """ + Computes how particle move + The basis is to add speed to current position + You can also add friction or compute distance to border in order to slow down + + """ + self.x += self.dx + self.y += self.dy + + + if self.dx > MAX_SPEED: + self.dx = MAX_SPEED + if self.dx < -MAX_SPEED: + self.dx = -MAX_SPEED + if self.dy > MAX_SPEED: + self.dy = MAX_SPEED + if self.dy < -MAX_SPEED: + self.dy = -MAX_SPEED + + + if self.x > MAX_WIDTH: + self.x = MIN_WIDTH + if self.x < MIN_WIDTH: + self.x = MAX_WIDTH + if self.y > MAX_HEIGHT: + self.y = MIN_HEIGHT + if self.y < MIN_HEIGHT: + self.y = MAX_HEIGHT + + + + + +class Simulator(object): + def __init__(self, particles): + """ + Defines the initial particles + """ + + # In this example, we will randomly dispatch a flock + for i in range(0,patricle_number): + x = random.randint(MIN_WIDTH,MAX_WIDTH) + y = random.randint(MIN_HEIGHT,MAX_HEIGHT) + dx = random.randint(-MAX_SPEED, MAX_SPEED) + dy = random.randint(-MAX_SPEED, MAX_SPEED) + color = WHITE + p = Particle(x,y,color,dx=dx,dy=dy) + cli.debug( "init: i:{} dx:{} dy:{} p:{}".format(i,dx,dy,vars(p))) + particles.append( p ) + self.particles = particles + + def redraw(self): + """ + Sends to standard output + A good place to use certain particles properties and draw more / less things + """ + pl = [] + for p in self.particles: + color = p.color + pl.append([p.x+1,p.y+1,0]) + pl.append([p.x+1,p.y+1,color]) + pl.append([p.x,p.y,color]) + + print(pl,flush = True) + + + def tick(self): + for p in self.particles: + p.interact(self.particles) + p.move() + self.redraw() + + +if __name__ == "__main__": + particles = [] + simulator = Simulator(particles) + try: + while True: + cli.startFrame() + simulator.tick() + cli.endFrame() + + except KeyboardInterrupt: + pass diff --git a/lib/clitools.py b/lib/clitools.py index 2c64b54..cb25553 100644 --- a/lib/clitools.py +++ b/lib/clitools.py @@ -29,7 +29,10 @@ class Clitools: if( elapsed < self.looptime ): delta = self.looptime - elapsed time.sleep( delta ) - self.debug(self.name + " micro sleep:" + str( delta )) def rgb2int(rgb): return int('0x%02x%02x%02x' % tuple(rgb),0) + + def msNow(): + return time.time() +