import time import random import math from galactic import GalacticUnicorn from picographics import PicoGraphics, DISPLAY_GALACTIC_UNICORN as DISPLAY ''' A 70s-tastic, procedural rainbow lava lamp. You can adjust the brightness with LUX + and -. ''' gu = GalacticUnicorn() graphics = PicoGraphics(DISPLAY) blob_count = 10 class Blob(): def __init__(self): self.x = float(random.randint(0, width - 1)) self.y = float(random.randint(0, height - 1)) self.r = (float(random.randint(0, 40)) / 10.0) + 5.0 self.dx = (float(random.randint(0, 2)) / 10.0) - 0.1 self.dy = (float(random.randint(0, 2)) / 10.0) - 0.05 # positive bias @micropython.native # noqa: F821 def setup_portrait(): global width, height, liquid, blobs width = GalacticUnicorn.HEIGHT height = GalacticUnicorn.WIDTH liquid = [[0.0 for y in range(height)] for x in range(width)] blobs = [Blob() for i in range(blob_count)] hue = 0.0 @micropython.native # noqa: F821 def from_hsv(h, s, v): i = math.floor(h * 6.0) f = h * 6.0 - i v *= 255.0 p = v * (1.0 - s) q = v * (1.0 - f * s) t = v * (1.0 - (1.0 - f) * s) i = int(i) % 6 if i == 0: return graphics.create_pen(int(v), int(t), int(p)) if i == 1: return graphics.create_pen(int(q), int(v), int(p)) if i == 2: return graphics.create_pen(int(p), int(v), int(t)) if i == 3: return graphics.create_pen(int(p), int(q), int(v)) if i == 4: return graphics.create_pen(int(t), int(p), int(v)) if i == 5: return graphics.create_pen(int(v), int(p), int(q)) @micropython.native # noqa: F821 def update_liquid(): for y in range(height): for x in range(width): liquid[x][y] = 0.0 for blob in blobs: r_sq = blob.r * blob.r blob_y_range = range(max(math.floor(blob.y - blob.r), 0), min(math.ceil(blob.y + blob.r), height)) blob_x_range = range(max(math.floor(blob.x - blob.r), 0), min(math.ceil(blob.x + blob.r), width)) for y in blob_y_range: for x in blob_x_range: x_diff = x - blob.x y_diff = y - blob.y d_sq = x_diff * x_diff + y_diff * y_diff if d_sq <= r_sq: liquid[x][y] += 1.0 - (d_sq / r_sq) @micropython.native # noqa: F821 def move_blobs(): for blob in blobs: blob.x += blob.dx blob.y += blob.dy if blob.x < 0.0 or blob.x >= float(width): blob.dx = 0.0 - blob.dx if blob.y < 0.0 or blob.y >= float(height): blob.dy = 0.0 - blob.dy @micropython.native # noqa: F821 def draw_portrait(): global hue hue += 0.001 dark = from_hsv(hue, 1.0, 0.3) mid = from_hsv(hue, 1.0, 0.6) bright = from_hsv(hue, 1.0, 1.0) for y in range(height): for x in range(width): v = liquid[x][y] # select a colour for this pixel based on how much # "blobfluence" there is at this position in the liquid if v >= 1.5: graphics.set_pen(bright) elif v >= 1.25: graphics.set_pen(mid) elif v >= 1.0: graphics.set_pen(dark) else: graphics.set_pen(0) graphics.pixel(y, x) gu.update(graphics) setup_portrait() gu.set_brightness(0.5) while True: if gu.is_pressed(GalacticUnicorn.SWITCH_BRIGHTNESS_UP): gu.adjust_brightness(+0.01) if gu.is_pressed(GalacticUnicorn.SWITCH_BRIGHTNESS_DOWN): gu.adjust_brightness(-0.01) if gu.is_pressed(GalacticUnicorn.SWITCH_A): setup_portrait() start = time.ticks_ms() update_liquid() move_blobs() draw_portrait() # pause for a moment (important or the USB serial device will fail) time.sleep(0.001) print("total took: {} ms".format(time.ticks_ms() - start))