Skip to content

Instantly share code, notes, and snippets.

@todbot
Last active May 20, 2024 01:16
Show Gist options
  • Save todbot/194298619de3cadb0c9f531b2461286a to your computer and use it in GitHub Desktop.
Save todbot/194298619de3cadb0c9f531b2461286a to your computer and use it in GitHub Desktop.
qteye.py but on a PicoDVI RP2040 board in CircuitPython
# qteye_picodvi.py - qteye.py but on a PicoDVI RP2040 board
# 19 May 2024 - @todbot, on a DJDevon3 suggestion in Discord
# 23 Oct 2022 - @todbot / Tod Kurt
# Part of https://github.com/todbot/CircuitPython_GC9A01_demos
# also see: https://twitter.com/todbot/status/1584309133263532033
# and: https://twitter.com/todbot/status/1584309133263532033
# Copy this file as "code.py" and the two eyeball BMP files to CIRCUITPY drive
# To install needed libraries: "circup install adafruit_imageload"
#
# Video demo below as a comment to this gist
import time, math, random
import board, busio
import displayio
import adafruit_imageload
display = board.DISPLAY
dw, dh = display.width, display.height # display dimensions
# load our eye and iris bitmaps
#eyeball_bitmap, eyeball_pal = adafruit_imageload.load("imgs/eye0_ball2.bmp")
# can't load both bitmaps fully in RAM on PicoDVI, so background eyeball is OnDisk
eyeball_bitmap = displayio.OnDiskBitmap("imgs/eye0_ball2.bmp")
eyeball_pal = eyeball_bitmap.pixel_shader
# and moving iris is loaded in RAM
iris_bitmap, iris_pal = adafruit_imageload.load("imgs/eye0_iris0.bmp")
iris_pal.make_transparent(0) # palette color #0 is our transparent background
# compute or declare some useful info about the eyes
iris_w, iris_h = iris_bitmap.width, iris_bitmap.height # iris is normally 110x110
iris_cx, iris_cy = dw//2 - iris_w//2, dh//2 - iris_h//2
r = 20 # allowable deviation from center for iris
main = displayio.Group()
display.root_group = main
# class to help us track eye info (not needed for this use exactly, but I find it interesting)
class Eye:
def __init__(self, display, main_group, rot=0, eye_speed=0.25, twitch=2):
self.display = display
self.main_group = main_group
self.eyeball = displayio.TileGrid(eyeball_bitmap, pixel_shader=eyeball_pal)
self.eyeball.x = (dw - eyeball_bitmap.width) // 2
self.iris = displayio.TileGrid(iris_bitmap, pixel_shader=iris_pal, x=iris_cx,y=iris_cy)
self.main_group.append(self.eyeball)
self.main_group.append(self.iris)
self.x, self.y = iris_cx, iris_cy
self.tx, self.ty = self.x, self.y
self.next_time = time.monotonic()
self.eye_speed = eye_speed
self.twitch = twitch
def update(self):
self.x = self.x * (1-self.eye_speed) + self.tx * self.eye_speed # "easing"
self.y = self.y * (1-self.eye_speed) + self.ty * self.eye_speed
self.iris.x = int( self.x )
self.iris.y = int( self.y )
if time.monotonic() > self.next_time:
t = random.uniform(0.25,self.twitch)
self.next_time = time.monotonic() + t
self.tx = iris_cx + random.uniform(-r,r)
self.ty = iris_cy + random.uniform(-r,r)
self.display.refresh()
# a list of all the eyes, in this case, only one
the_eyes = [
Eye( display, main, rot=0),
]
while True:
for eye in the_eyes:
eye.update()
@todbot
Copy link
Author

todbot commented May 20, 2024

Video demo:

IMG_3834.mov

@DJDevon3
Copy link

That's one giant eyeball. Very nice!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment