|
1 | | -# Two projectiles are sent from random positions and collide with each other |
2 | | -# Template from https://github.com/nickpesce/lit/blob/master/lit/effects/collision.py |
3 | 1 | import hyperion, time, colorsys, random |
4 | 2 |
|
5 | 3 | # Get parameters |
6 | 4 | sleepTime = max(0.02, float(hyperion.args.get('speed', 100))/1000.0) |
7 | 5 | trailLength = max(3, int(hyperion.args.get('trailLength', 5))) |
8 | 6 | explodeRadius = int(hyperion.args.get('explodeRadius', 8)) |
9 | 7 |
|
| 8 | +# Ensure that the range for pixel indices stays within bounds |
| 9 | +maxPixelIndex = hyperion.ledCount - 1 |
| 10 | +if trailLength > maxPixelIndex or explodeRadius > maxPixelIndex: |
| 11 | + exit(f"Error: Color length ({trailLength}) and detonation range ({explodeRadius}) must be less than number of LEDs configured ({hyperion.ledCount})") |
| 12 | + |
10 | 13 | # Create additional variables |
11 | 14 | increment = None |
12 | 15 | projectiles = [] |
13 | 16 |
|
14 | 17 | # Initialize the led data |
15 | 18 | ledData = bytearray() |
16 | 19 | for i in range(hyperion.ledCount): |
17 | | - ledData += bytearray((0,0,0)) |
| 20 | + ledData += bytearray((0,0,0)) |
18 | 21 |
|
19 | 22 | # Start the write data loop |
20 | 23 | while not hyperion.abort(): |
21 | | - if (len(projectiles) != 2): |
22 | | - projectiles = [ [0, 1, random.uniform(0.0, 1.0)], [hyperion.ledCount-1, -1, random.uniform(0.0, 1.0)] ] |
23 | | - increment = -random.randint(0, hyperion.ledCount-1) if random.choice([True, False]) else random.randint(0, hyperion.ledCount-1) |
24 | | - |
25 | | - ledDataBuf = ledData[:] |
26 | | - for i, v in enumerate(projectiles): |
27 | | - projectiles[i][0] = projectiles[i][0]+projectiles[i][1] |
28 | | - for t in range(0, trailLength): |
29 | | - pixel = v[0] - v[1]*t |
30 | | - if pixel + 2 < 0: |
31 | | - pixel += hyperion.ledCount |
32 | | - if pixel + 2 > hyperion.ledCount-1: |
33 | | - pixel -= hyperion.ledCount-1 |
34 | | - rgb = colorsys.hsv_to_rgb(v[2], 1, (trailLength - 1.0*t)/trailLength) |
35 | | - ledDataBuf[3*pixel ] = int(255*rgb[0]) |
36 | | - ledDataBuf[3*pixel + 1] = int(255*rgb[1]) |
37 | | - ledDataBuf[3*pixel + 2] = int(255*rgb[2]) |
38 | | - |
39 | | - hyperion.setColor(ledDataBuf[-increment:] + ledDataBuf[:-increment]) |
40 | | - |
41 | | - for i1, p1 in enumerate(projectiles): |
42 | | - for i2, p2 in enumerate(projectiles): |
43 | | - if (p1 is not p2): |
44 | | - prev1 = p1[0] - p1[1] |
45 | | - prev2 = p2[0] - p2[1] |
46 | | - if (prev1 - prev2 < 0) != (p1[0] - p2[0] < 0): |
47 | | - for d in range(0, explodeRadius): |
48 | | - for pixel in range(p1[0] - d, p1[0] + d): |
49 | | - rgb = colorsys.hsv_to_rgb(random.choice([p1[2], p2[2]]), 1, (1.0 * explodeRadius - d) / explodeRadius) |
50 | | - ledDataBuf[3*pixel ] = int(255*rgb[0]) |
51 | | - ledDataBuf[3*pixel + 1] = int(255*rgb[1]) |
52 | | - ledDataBuf[3*pixel + 2] = int(255*rgb[2]) |
53 | | - |
54 | | - hyperion.setColor(ledDataBuf[-increment:] + ledDataBuf[:-increment]) |
55 | | - time.sleep(sleepTime) |
56 | | - |
57 | | - projectiles.remove(p1) |
58 | | - projectiles.remove(p2) |
59 | | - |
60 | | - time.sleep(sleepTime) |
| 24 | + if len(projectiles) != 2: |
| 25 | + projectiles = [ |
| 26 | + [0, 1, random.uniform(0.0, 1.0)], # Start positions of projectiles |
| 27 | + [hyperion.ledCount-1, -1, random.uniform(0.0, 1.0)] |
| 28 | + ] |
| 29 | + increment = -random.randint(0, hyperion.ledCount-1) if random.choice([True, False]) else random.randint(0, hyperion.ledCount-1) |
| 30 | + |
| 31 | + # Backup the LED data |
| 32 | + ledDataBuf = ledData[:] |
| 33 | + for i, v in enumerate(projectiles): |
| 34 | + # Update projectile positions |
| 35 | + projectiles[i][0] = projectiles[i][0] + projectiles[i][1] |
| 36 | + |
| 37 | + for t in range(0, trailLength): |
| 38 | + # Calculate pixel index for the trail |
| 39 | + pixel = v[0] - v[1] * t |
| 40 | + if pixel < 0: |
| 41 | + pixel += hyperion.ledCount |
| 42 | + if pixel >= hyperion.ledCount: |
| 43 | + pixel -= hyperion.ledCount |
| 44 | + |
| 45 | + # Make sure pixel is within bounds |
| 46 | + if pixel < 0 or pixel >= hyperion.ledCount: |
| 47 | + continue |
| 48 | + |
| 49 | + rgb = colorsys.hsv_to_rgb(v[2], 1, (trailLength - 1.0 * t) / trailLength) |
| 50 | + ledDataBuf[3*pixel] = int(255 * rgb[0]) |
| 51 | + ledDataBuf[3*pixel + 1] = int(255 * rgb[1]) |
| 52 | + ledDataBuf[3*pixel + 2] = int(255 * rgb[2]) |
| 53 | + |
| 54 | + hyperion.setColor(ledDataBuf[-increment:] + ledDataBuf[:-increment]) |
| 55 | + |
| 56 | + # Check for collision and handle explosion |
| 57 | + for i1, p1 in enumerate(projectiles): |
| 58 | + for i2, p2 in enumerate(projectiles): |
| 59 | + if p1 is not p2: |
| 60 | + prev1 = p1[0] - p1[1] |
| 61 | + prev2 = p2[0] - p2[1] |
| 62 | + if (prev1 - prev2 < 0) != (p1[0] - p2[0] < 0): |
| 63 | + for d in range(0, explodeRadius): |
| 64 | + for pixel in range(p1[0] - d, p1[0] + d): |
| 65 | + # Check if pixel is out of bounds |
| 66 | + if pixel < 0 or pixel >= hyperion.ledCount: |
| 67 | + continue |
| 68 | + |
| 69 | + rgb = colorsys.hsv_to_rgb(random.choice([p1[2], p2[2]]), 1, (1.0 * explodeRadius - d) / explodeRadius) |
| 70 | + ledDataBuf[3 * pixel] = int(255 * rgb[0]) |
| 71 | + ledDataBuf[3 * pixel + 1] = int(255 * rgb[1]) |
| 72 | + ledDataBuf[3 * pixel + 2] = int(255 * rgb[2]) |
| 73 | + |
| 74 | + hyperion.setColor(ledDataBuf[-increment:] + ledDataBuf[:-increment]) |
| 75 | + time.sleep(sleepTime) |
| 76 | + |
| 77 | + projectiles.remove(p1) |
| 78 | + projectiles.remove(p2) |
| 79 | + |
| 80 | + time.sleep(sleepTime) |
0 commit comments