blue_green_flames.py (6537B)
1 #!/usr/bin/env python3 2 3 import time 4 from rpi_ws281x import Color 5 import random 6 import sys 7 import PyIgnition, pygame, os 8 import subprocess 9 import math 10 11 import patterns 12 13 class BlueGreenFlames(patterns.Pattern): 14 def __init__(self, strip, led_matrix_width, led_matrix_height, led_strip_snake, opts=None): 15 patterns.Pattern.__init__(self, strip=strip, led_matrix_width=led_matrix_width, led_matrix_height=led_matrix_height, led_strip_snake = led_strip_snake, opts=opts) 16 # This mode works great with LED_BRIGHTNESS set to 16. 17 self.SCALE=40 # Scaling factor for screen 18 19 # Also show in window? 20 # self.HEADLESS=False 21 self.HEADLESS=True 22 23 if self.HEADLESS: 24 # On Raspbian, setting a dummy videodriver 25 # does not prevent pygame from trying to 26 # open a X display. Therefore we use a 27 # virtual framebuffer. 28 os.environ["SDL_VIDEODRIVER"] = "dummy" 29 subprocess.Popen(["Xvfb", ":1", "-screen", "0", "1024x768x24"], 30 stderr=subprocess.DEVNULL) 31 time.sleep(1) 32 os.environ["DISPLAY"] = ":1" 33 34 pygame.display.init() 35 self.screen = pygame.Surface((math.ceil(self.led_matrix_width), 36 math.ceil(self.led_matrix_height))) 37 self.screen_scaled = pygame.display.set_mode((math.ceil(self.led_matrix_width*self.SCALE), 38 math.ceil(self.led_matrix_height*self.SCALE))) 39 pygame.display.set_caption("Blue Green Fire") 40 self.clock = pygame.time.Clock() 41 42 self.fire = PyIgnition.ParticleEffect(self.screen, (0, 0), 43 (math.ceil(self.led_matrix_width), 44 math.ceil(self.led_matrix_height))) 45 gravity = self.fire.CreateDirectedGravity(strength=0.1, direction=[0, -1]) 46 47 # Behavior of blue particles 48 self.blue_flames = [] 49 blue_flames_scale_factor = 4 50 for x_pos in range(0, math.ceil(self.led_matrix_width), 51 math.ceil(self.led_matrix_width//5)): 52 new_flame = self.fire.CreateSource(pos=(x_pos, self.led_matrix_height*1.1), 53 initspeed = .01, initdirection = 0.0, 54 initspeedrandrange = .1, 55 initdirectionrandrange = 0.5, 56 particlesperframe = 1, 57 particlelife = 100, 58 drawtype = PyIgnition.DRAWTYPE_CIRCLE, 59 colour = (65, 25, 255), 60 radius = self.led_matrix_width/32.0*blue_flames_scale_factor) 61 new_flame.CreateParticleKeyframe(1, colour = (65, 25, 255), 62 radius = self.led_matrix_width/32.0*blue_flames_scale_factor) 63 new_flame.CreateParticleKeyframe(3, colour = (0, 0, 190), 64 radius = self.led_matrix_width/32.0*blue_flames_scale_factor) 65 new_flame.CreateParticleKeyframe(6, colour = (25, 25, 65), 66 radius = self.led_matrix_width/32.0*blue_flames_scale_factor) 67 new_flame.CreateParticleKeyframe(9, colour = (0, 0, 0), 68 radius = self.led_matrix_width/32.0*blue_flames_scale_factor) 69 self.blue_flames += [new_flame] 70 71 # Behavior of green particle 72 self.green_flame_x = self.led_matrix_width / 2 73 self.green_flame_y = self.led_matrix_height + 1 74 self.green_flame = self.fire.CreateSource(pos=(self.green_flame_x, self.green_flame_y), 75 initspeed = .3, initdirection = 0.0, 76 initspeedrandrange = .3, 77 initdirectionrandrange = 0.5, 78 particlesperframe = 1, particlelife = 100, 79 drawtype = PyIgnition.DRAWTYPE_CIRCLE, 80 colour = (255, 255, 130), 81 radius = self.led_matrix_width/36.0) 82 self.green_flame.CreateParticleKeyframe(5, colour = (65, 255, 25), 83 radius = self.led_matrix_width/36.0) 84 self.green_flame.CreateParticleKeyframe(10, colour = (0, 190, 0), 85 radius = self.led_matrix_width/36.0) 86 self.green_flame.CreateParticleKeyframe(15, colour = (25, 65, 25), 87 radius = self.led_matrix_width/36.0) 88 self.green_flame.CreateParticleKeyframe(20, colour = (0, 0, 0), 89 radius = self.led_matrix_width/36.0) 90 91 def step(self): 92 # Draw on screen 93 self.screen.fill((0, 0, 0)) 94 self.green_flame_x = random.randint(0, math.ceil(self.led_matrix_width)-1) 95 self.green_flame.pos = (self.green_flame_x, self.green_flame_y) 96 if self.green_flame.curframe % 10 == 0: 97 self.green_flame.ConsolidateKeyframes() 98 for b in self.blue_flames: 99 if b.curframe % 30 == 0: 100 b.ConsolidateKeyframes() 101 self.fire.Update() 102 self.fire.Redraw() 103 pygame.transform.scale(self.screen, (math.ceil(self.led_matrix_width*self.SCALE), 104 math.ceil(self.led_matrix_height*self.SCALE)), 105 self.screen_scaled) 106 pygame.display.update() 107 # Draw on LED matrix 108 fb = pygame.PixelArray(self.screen) 109 for y in range(math.ceil(self.led_matrix_height)): 110 for x in range(math.ceil(self.led_matrix_width)): 111 r = fb[x][y] >> 16 & 0xFF 112 g = fb[x][y] >> 8 & 0xFF 113 b = fb[x][y] & 0xFF 114 self.strip.setPixelColor(self.xy2i(x, 115 math.ceil(self.led_matrix_height)-1-y), 116 Color(r, g, b)) 117 self.strip.show() 118 self.clock.tick(5)