diff --git a/Macropad_Dragon_Drop/code.py b/Macropad_Dragon_Drop/code.py index 37d81f56c..c3580030c 100644 --- a/Macropad_Dragon_Drop/code.py +++ b/Macropad_Dragon_Drop/code.py @@ -31,19 +31,19 @@ def background_sound(filename): """ Start a WAV file playing in the background (non-blocking). This func can be removed if/when MacroPad lib gets background audio. """ # pylint: disable=protected-access - MACROPAD._speaker_enable.value = True - AUDIO.play(audiocore.WaveFile(open(PATH + filename, 'rb'))) + macropad._speaker_enable.value = True + audio.play(audiocore.WaveFile(open(PATH + filename, 'rb'))) def show_screen(group): """ Activate a given displayio group, pause until keypress. """ - MACROPAD.display.show(group) - MACROPAD.display.refresh() + macropad.display.show(group) + macropad.display.refresh() # Purge any queued up key events... - while MACROPAD.keys.events.get(): + while macropad.keys.events.get(): pass while True: # ...then wait for first new key press event - event = MACROPAD.keys.events.get() - if event and event.pressed: + key_event = macropad.keys.events.get() + if key_event and key_event.pressed: return # pylint: disable=too-few-public-methods @@ -58,228 +58,228 @@ class Sprite: # ONE-TIME INITIALIZATION -------------- -MACROPAD = MacroPad(rotation=90) -MACROPAD.display.auto_refresh = False -MACROPAD.pixels.auto_write = False -MACROPAD.pixels.brightness = 0.5 -AUDIO = audiopwmio.PWMAudioOut(board.SPEAKER) # For background audio +macropad = MacroPad(rotation=90) +macropad.display.auto_refresh = False +macropad.pixels.auto_write = False +macropad.pixels.brightness = 0.5 +audio = audiopwmio.PWMAudioOut(board.SPEAKER) # For background audio -FONT = bitmap_font.load_font(PATH + 'cursive-smart.pcf') +font = bitmap_font.load_font(PATH + 'cursive-smart.pcf') # Create 3 displayio groups -- one each for the title, play and end screens. -TITLE_GROUP = displayio.Group() -TITLE_BITMAP, TITLE_PALETTE = adafruit_imageload.load(PATH + 'title.bmp', +title_group = displayio.Group() +title_bitmap, title_palette = adafruit_imageload.load(PATH + 'title.bmp', bitmap=displayio.Bitmap, palette=displayio.Palette) -TITLE_GROUP.append(displayio.TileGrid(TITLE_BITMAP, pixel_shader=TITLE_PALETTE, +title_group.append(displayio.TileGrid(title_bitmap, pixel_shader=title_palette, width=1, height=1, - tile_width=TITLE_BITMAP.width, - tile_height=TITLE_BITMAP.height)) + tile_width=title_bitmap.width, + tile_height=title_bitmap.height)) # Bitmap containing eggs, hatchling and fireballs -SPRITE_BITMAP, SPRITE_PALETTE = adafruit_imageload.load( +sprite_bitmap, sprite_palette = adafruit_imageload.load( PATH + 'sprites.bmp', bitmap=displayio.Bitmap, palette=displayio.Palette) -SPRITE_PALETTE.make_transparent(0) +sprite_palette.make_transparent(0) -PLAY_GROUP = displayio.Group() +play_group = displayio.Group() # Bitmap containing five shadow tiles ('no shadow' through 'max shadow') -SHADOW_BITMAP, SHADOW_PALETTE = adafruit_imageload.load( +shadow_bitmap, shadow_palette = adafruit_imageload.load( PATH + 'shadow.bmp', bitmap=displayio.Bitmap, palette=displayio.Palette) # Tilegrid with four shadow tiles; one per column -SHADOW = displayio.TileGrid(SHADOW_BITMAP, pixel_shader=SHADOW_PALETTE, +shadow = displayio.TileGrid(shadow_bitmap, pixel_shader=shadow_palette, width=4, height=1, tile_width=16, - tile_height=SHADOW_BITMAP.height, x=0, - y=MACROPAD.display.height - SHADOW_BITMAP.height) -PLAY_GROUP.append(SHADOW) -SHADOW_SCALE = 5 / (MACROPAD.display.height - 20) # For picking shadow sprite -LIFE_BAR = HorizontalProgressBar((0, 0), (MACROPAD.display.width, 7), + tile_height=shadow_bitmap.height, x=0, + y=macropad.display.height - shadow_bitmap.height) +play_group.append(shadow) +shadow_scale = 5 / (macropad.display.height - 20) # For picking shadow sprite +life_bar = HorizontalProgressBar((0, 0), (macropad.display.width, 7), value=100, min_value=0, max_value=100, bar_color=0xFFFFFF, outline_color=0xFFFFFF, fill_color=0, margin_size=1) -PLAY_GROUP.append(LIFE_BAR) -# Score is last object in PLAY_GROUP, can be indexed as -1 -PLAY_GROUP.append(label.Label(FONT, text='0', color=0xFFFFFF, +play_group.append(life_bar) +# Score is last object in play_group, can be indexed as -1 +play_group.append(label.Label(font, text='0', color=0xFFFFFF, anchor_point=(0.5, 0.0), - anchored_position=(MACROPAD.display.width // 2, + anchored_position=(macropad.display.width // 2, 10))) -END_GROUP = displayio.Group() -END_BITMAP, END_PALETTE = adafruit_imageload.load( +end_group = displayio.Group() +end_bitmap, end_palette = adafruit_imageload.load( PATH + 'gameover.bmp', bitmap=displayio.Bitmap, palette=displayio.Palette) -END_GROUP.append(displayio.TileGrid(END_BITMAP, pixel_shader=END_PALETTE, +end_group.append(displayio.TileGrid(end_bitmap, pixel_shader=end_palette, width=1, height=1, - tile_width=END_BITMAP.width, - tile_height=END_BITMAP.height)) -END_GROUP.append(label.Label(FONT, text='0', color=0xFFFFFF, + tile_width=end_bitmap.width, + tile_height=end_bitmap.height)) +end_group.append(label.Label(font, text='0', color=0xFFFFFF, anchor_point=(0.5, 0.0), - anchored_position=(MACROPAD.display.width // 2, + anchored_position=(macropad.display.width // 2, 90))) # MAIN LOOP -- alternates play and end-game screens -------- -show_screen(TITLE_GROUP) # Just do this once on startup +show_screen(title_group) # Just do this once on startup while True: # NEW GAME ------------------------- - SPRITES = [] - SCORE = 0 - PLAY_GROUP[-1].text = '0' # Score text - LIFE_BAR.value = 100 - AUDIO.stop() - MACROPAD.display.show(PLAY_GROUP) - MACROPAD.display.refresh() - START_TIME = time.monotonic() + sprites = [] + score = 0 + play_group[-1].text = '0' # Score text + life_bar.value = 100 + audio.stop() + macropad.display.show(play_group) + macropad.display.refresh() + start = time.monotonic() # PLAY UNTIL LIFE BAR DEPLETED ----- - while LIFE_BAR.value > 0: - NOW = time.monotonic() - SPEED = 10 + (NOW - START_TIME) / 30 # Gradually speed up - FIRE_SPRITE = 3 + int((NOW * 6) % 2.0) # For animating fire + while life_bar.value > 0: + now = time.monotonic() + speed = 10 + (now - start) / 30 # Gradually speed up + fire_sprite = 3 + int((now * 6) % 2.0) # For animating fire # Coalese any/all queued-up keypress events per column - COLUMN_PRESSED = [False] * 4 + column_pressed = [False] * 4 while True: - EVENT = MACROPAD.keys.events.get() - if not EVENT: + event = macropad.keys.events.get() + if not event: break - if EVENT.pressed: - COLUMN_PRESSED[EVENT.key_number % 4] = True + if event.pressed: + column_pressed[event.key_number % 4] = True # For determining upper/lower extents of active egg sprites per column - COLUMN_MIN = [MACROPAD.display.height] * 4 - COLUMN_MAX = [0] * 4 + column_min = [macropad.display.height] * 4 + column_max = [0] * 4 # Traverse sprite list backwards so we can pop() without index problems - for i in range(len(SPRITES) - 1, -1, -1): - sprite = SPRITES[i] - tile = PLAY_GROUP[i + 1] # Corresponding 1x1 TileGrid for sprite + for i in range(len(sprites) - 1, -1, -1): + sprite = sprites[i] + tile = play_group[i + 1] # Corresponding 1x1 TileGrid for sprite column = sprite.column - elapsed = NOW - sprite.start_time # Time since add or pause event + elapsed = now - sprite.start_time # Time since add or pause event if sprite.is_fire: - tile[0] = FIRE_SPRITE # Animate all flame sprites + tile[0] = fire_sprite # Animate all flame sprites if sprite.paused: # Sprite at bottom of screen if elapsed > 0.75: # Hold position for 3/4 second, for x in range(0, 9, 4): # then LEDs off, - MACROPAD.pixels[x + sprite.column] = (0, 0, 0) - SPRITES.pop(i) # and delete Sprite object and - PLAY_GROUP.pop(i + 1) # element from displayio group + macropad.pixels[x + sprite.column] = (0, 0, 0) + sprites.pop(i) # and delete Sprite object and + play_group.pop(i + 1) # element from displayio group continue if not sprite.is_fire: - COLUMN_MAX[column] = max(COLUMN_MAX[column], - MACROPAD.display.height - 22) + column_max[column] = max(column_max[column], + macropad.display.height - 22) else: # Sprite in motion - y = SPEED * elapsed * elapsed - 16 + y = speed * elapsed * elapsed - 16 # Track top of all sprites, bottom of eggs only - COLUMN_MIN[column] = min(COLUMN_MIN[column], y) + column_min[column] = min(column_min[column], y) if not sprite.is_fire: - COLUMN_MAX[column] = max(COLUMN_MAX[column], y) - tile.y = int(y) # Sprite's vertical pos. in PLAY_GROUP + column_max[column] = max(column_max[column], y) + tile.y = int(y) # Sprite's vertical pos. in play_group # Handle various catch or off-bottom actions... if sprite.is_fire: - if y >= MACROPAD.display.height: # Off bottom of screen, - SPRITES.pop(i) # remove fireball sprite - PLAY_GROUP.pop(i + 1) + if y >= macropad.display.height: # Off bottom of screen, + sprites.pop(i) # remove fireball sprite + play_group.pop(i + 1) continue - elif y >= MACROPAD.display.height - 40: - if COLUMN_PRESSED[column]: + if y >= macropad.display.height - 40: + if column_pressed[column]: # Fireball caught, ouch! background_sound('sizzle.wav') # I smell bacon sprite.paused = True - sprite.start_time = NOW - tile.y = MACROPAD.display.height - 20 - LIFE_BAR.value = max(0, LIFE_BAR.value - 5) + sprite.start_time = now + tile.y = macropad.display.height - 20 + life_bar.value = max(0, life_bar.value - 5) for x in range(0, 9, 4): - MACROPAD.pixels[x + sprite.column] = (255, 0, 0) + macropad.pixels[x + sprite.column] = (255, 0, 0) else: # Is egg... - if y >= MACROPAD.display.height - 22: + if y >= macropad.display.height - 22: # Egg hit ground background_sound('splat.wav') sprite.paused = True - sprite.start_time = NOW - tile.y = MACROPAD.display.height - 22 + sprite.start_time = now + tile.y = macropad.display.height - 22 tile[0] = 1 # Change sprite to broken egg - LIFE_BAR.value = max(0, LIFE_BAR.value - 5) - MACROPAD.pixels[8 + sprite.column] = (255, 255, 0) - elif COLUMN_PRESSED[column]: - if y >= MACROPAD.display.height - 40: + life_bar.value = max(0, life_bar.value - 5) + macropad.pixels[8 + sprite.column] = (255, 255, 0) + elif column_pressed[column]: + if y >= macropad.display.height - 40: # Egg caught at right time background_sound('rawr.wav') sprite.paused = True - sprite.start_time = NOW - tile.y = MACROPAD.display.height - 22 + sprite.start_time = now + tile.y = macropad.display.height - 22 tile[0] = 2 # Hatchling - MACROPAD.pixels[4 + sprite.column] = (0, 255, 0) - SCORE += 10 - PLAY_GROUP[-1].text = str(SCORE) - elif y >= MACROPAD.display.height - 58: + macropad.pixels[4 + sprite.column] = (0, 255, 0) + score += 10 + play_group[-1].text = str(score) + elif y >= macropad.display.height - 58: # Egg caught too early background_sound('splat.wav') sprite.paused = True - sprite.start_time = NOW - tile.y = MACROPAD.display.height - 40 + sprite.start_time = now + tile.y = macropad.display.height - 40 tile[0] = 1 # Broken egg - LIFE_BAR.value = max(0, LIFE_BAR.value - 5) - MACROPAD.pixels[sprite.column] = (255, 255, 0) + life_bar.value = max(0, life_bar.value - 5) + macropad.pixels[sprite.column] = (255, 255, 0) # Select shadow bitmaps based on each column's lowest egg for i in range(4): - SHADOW[i] = min(4, int(COLUMN_MAX[i] * SHADOW_SCALE)) + shadow[i] = min(4, int(column_max[i] * shadow_scale)) # Time to introduce a new sprite? 1/20 chance each frame, if space - if (len(SPRITES) < MAX_EGGS and random.random() < 0.05 and - max(COLUMN_MIN) > 16): + if (len(sprites) < MAX_EGGS and random.random() < 0.05 and + max(column_min) > 16): # Pick a column randomly...if it's occupied, keep trying... while True: - COLUMN = random.randint(0, 3) - if COLUMN_MIN[COLUMN] > 16: + column = random.randint(0, 3) + if column_min[column] > 16: # Found a clear spot. Add sprite and break loop - SPRITES.append(Sprite(COLUMN, NOW)) - PLAY_GROUP.insert(-2, displayio.TileGrid(SPRITE_BITMAP, - pixel_shader=SPRITE_PALETTE, + sprites.append(Sprite(column, now)) + play_group.insert(-2, displayio.TileGrid(sprite_bitmap, + pixel_shader=sprite_palette, width=1, height=1, tile_width=16, - tile_height=SPRITE_BITMAP.height, - x=COLUMN * 16, + tile_height=sprite_bitmap.height, + x=column * 16, y=-16)) break - MACROPAD.display.refresh() - MACROPAD.pixels.show() - if not AUDIO.playing: + macropad.display.refresh() + macropad.pixels.show() + if not audio.playing: # pylint: disable=protected-access - MACROPAD._speaker_enable.value = False + macropad._speaker_enable.value = False gc.collect() # Encoder button pauses/resumes game. - MACROPAD.encoder_switch_debounced.update() - if MACROPAD.encoder_switch_debounced.pressed: + macropad.encoder_switch_debounced.update() + if macropad.encoder_switch_debounced.pressed: for n in (True, False, True): # Press, release, press - while n == MACROPAD.encoder_switch_debounced.pressed: - MACROPAD.encoder_switch_debounced.update() + while n == macropad.encoder_switch_debounced.pressed: + macropad.encoder_switch_debounced.update() # Sprite start times must be offset by pause duration # because time.monotonic() is used for drop physics. - NOW = time.monotonic() - NOW # Pause duration - for sprite in SPRITES: - sprite.start_time += NOW + now = time.monotonic() - now # Pause duration + for sprite in sprites: + sprite.start_time += now # GAME OVER ------------------------ time.sleep(1.5) # Pause display for a moment - MACROPAD.pixels.fill(0) - MACROPAD.pixels.show() + macropad.pixels.fill(0) + macropad.pixels.show() # pylint: disable=protected-access - MACROPAD._speaker_enable.value = False - # Pop any sprites from PLAY_GROUP (other elements remain, and SPRITES[] + macropad._speaker_enable.value = False + # Pop any sprites from play_group (other elements remain, and sprites[] # list is cleared at start of next game). - for _ in SPRITES: - PLAY_GROUP.pop(1) - END_GROUP[-1].text = str(SCORE) - show_screen(END_GROUP) + for _ in sprites: + play_group.pop(1) + end_group[-1].text = str(score) + show_screen(end_group) diff --git a/Macropad_Hotkeys/code.py b/Macropad_Hotkeys/code.py index f15b9cb2b..85cf40495 100755 --- a/Macropad_Hotkeys/code.py +++ b/Macropad_Hotkeys/code.py @@ -34,116 +34,116 @@ class App: def switch(self): """ Activate application settings; update OLED labels and LED colors. """ - GROUP[13].text = self.name # Application name + group[13].text = self.name # Application name for i in range(12): if i < len(self.macros): # Key in use, set label + LED color - MACROPAD.pixels[i] = self.macros[i][0] - GROUP[i].text = self.macros[i][1] + macropad.pixels[i] = self.macros[i][0] + group[i].text = self.macros[i][1] else: # Key not in use, no label or LED - MACROPAD.pixels[i] = 0 - GROUP[i].text = '' - MACROPAD.keyboard.release_all() - MACROPAD.pixels.show() - MACROPAD.display.refresh() + macropad.pixels[i] = 0 + group[i].text = '' + macropad.keyboard.release_all() + macropad.pixels.show() + macropad.display.refresh() # INITIALIZATION ----------------------- -MACROPAD = MacroPad() -MACROPAD.display.auto_refresh = False -MACROPAD.pixels.auto_write = False +macropad = MacroPad() +macropad.display.auto_refresh = False +macropad.pixels.auto_write = False # Set up displayio group with all the labels -GROUP = displayio.Group() -for KEY_INDEX in range(12): - x = KEY_INDEX % 3 - y = KEY_INDEX // 3 - GROUP.append(label.Label(terminalio.FONT, text='', color=0xFFFFFF, - anchored_position=((MACROPAD.display.width - 1) * x / 2, - MACROPAD.display.height - 1 - +group = displayio.Group() +for key_index in range(12): + x = key_index % 3 + y = key_index // 3 + group.append(label.Label(terminalio.FONT, text='', color=0xFFFFFF, + anchored_position=((macropad.display.width - 1) * x / 2, + macropad.display.height - 1 - (3 - y) * 12), anchor_point=(x / 2, 1.0))) -GROUP.append(Rect(0, 0, MACROPAD.display.width, 12, fill=0xFFFFFF)) -GROUP.append(label.Label(terminalio.FONT, text='', color=0x000000, - anchored_position=(MACROPAD.display.width//2, -2), +group.append(Rect(0, 0, macropad.display.width, 12, fill=0xFFFFFF)) +group.append(label.Label(terminalio.FONT, text='', color=0x000000, + anchored_position=(macropad.display.width//2, -2), anchor_point=(0.5, 0.0))) -MACROPAD.display.show(GROUP) +macropad.display.show(group) # Load all the macro key setups from .py files in MACRO_FOLDER -APPS = [] -FILES = os.listdir(MACRO_FOLDER) -FILES.sort() -for FILENAME in FILES: - if FILENAME.endswith('.py'): +apps = [] +files = os.listdir(MACRO_FOLDER) +files.sort() +for filename in files: + if filename.endswith('.py'): try: - module = __import__(MACRO_FOLDER + '/' + FILENAME[:-3]) - APPS.append(App(module.app)) + module = __import__(MACRO_FOLDER + '/' + filename[:-3]) + apps.append(App(module.app)) except (SyntaxError, ImportError, AttributeError, KeyError, NameError, IndexError, TypeError) as err: pass -if not APPS: - GROUP[13].text = 'NO MACRO FILES FOUND' - MACROPAD.display.refresh() +if not apps: + group[13].text = 'NO MACRO FILES FOUND' + macropad.display.refresh() while True: pass -LAST_POSITION = None -LAST_ENCODER_SWITCH = MACROPAD.encoder_switch_debounced.pressed -APP_INDEX = 0 -APPS[APP_INDEX].switch() +last_position = None +last_encoder_switch = macropad.encoder_switch_debounced.pressed +app_index = 0 +apps[app_index].switch() # MAIN LOOP ---------------------------- while True: # Read encoder position. If it's changed, switch apps. - POSITION = MACROPAD.encoder - if POSITION != LAST_POSITION: - APP_INDEX = POSITION % len(APPS) - APPS[APP_INDEX].switch() - LAST_POSITION = POSITION + position = macropad.encoder + if position != last_position: + app_index = position % len(apps) + apps[app_index].switch() + last_position = position # Handle encoder button. If state has changed, and if there's a # corresponding macro, set up variables to act on this just like # the keypad keys, as if it were a 13th key/macro. - MACROPAD.encoder_switch_debounced.update() - ENCODER_SWITCH = MACROPAD.encoder_switch_debounced.pressed - if ENCODER_SWITCH != LAST_ENCODER_SWITCH: - LAST_ENCODER_SWITCH = ENCODER_SWITCH - if len(APPS[APP_INDEX].macros) < 13: + macropad.encoder_switch_debounced.update() + encoder_switch = macropad.encoder_switch_debounced.pressed + if encoder_switch != last_encoder_switch: + last_encoder_switch = encoder_switch + if len(apps[app_index].macros) < 13: continue # No 13th macro, just resume main loop - KEY_NUMBER = 12 # else process below as 13th macro - PRESSED = ENCODER_SWITCH + key_number = 12 # else process below as 13th macro + pressed = encoder_switch else: - EVENT = MACROPAD.keys.events.get() - if not EVENT or EVENT.key_number >= len(APPS[APP_INDEX].macros): + event = macropad.keys.events.get() + if not event or event.key_number >= len(apps[app_index].macros): continue # No key events, or no corresponding macro, resume loop - KEY_NUMBER = EVENT.key_number - PRESSED = EVENT.pressed + key_number = event.key_number + pressed = event.pressed # If code reaches here, a key or the encoder button WAS pressed/released # and there IS a corresponding macro available for it...other situations # are avoided by 'continue' statements above which resume the loop. - SEQUENCE = APPS[APP_INDEX].macros[KEY_NUMBER][2] - if PRESSED: - if KEY_NUMBER < 12: # No pixel for encoder button - MACROPAD.pixels[KEY_NUMBER] = 0xFFFFFF - MACROPAD.pixels.show() - for item in SEQUENCE: + sequence = apps[app_index].macros[key_number][2] + if pressed: + if key_number < 12: # No pixel for encoder button + macropad.pixels[key_number] = 0xFFFFFF + macropad.pixels.show() + for item in sequence: if isinstance(item, int): if item >= 0: - MACROPAD.keyboard.press(item) + macropad.keyboard.press(item) else: - MACROPAD.keyboard.release(-item) + macropad.keyboard.release(-item) else: - MACROPAD.keyboard_layout.write(item) + macropad.keyboard_layout.write(item) else: # Release any still-pressed modifier keys - for item in SEQUENCE: + for item in sequence: if isinstance(item, int) and item >= 0: - MACROPAD.keyboard.release(item) - if KEY_NUMBER < 12: # No pixel for encoder button - MACROPAD.pixels[KEY_NUMBER] = APPS[APP_INDEX].macros[KEY_NUMBER][0] - MACROPAD.pixels.show() + macropad.keyboard.release(item) + if key_number < 12: # No pixel for encoder button + macropad.pixels[key_number] = apps[app_index].macros[key_number][0] + macropad.pixels.show() diff --git a/Macropad_Hotkeys/macros/numpad.py b/Macropad_Hotkeys/macros/numpad.py index 8339b6df6..ccdbd977a 100644 --- a/Macropad_Hotkeys/macros/numpad.py +++ b/Macropad_Hotkeys/macros/numpad.py @@ -9,7 +9,7 @@ app = { # REQUIRED dict, must be named 'app' # 1st row ---------- (0x202000, '7', ['7']), (0x202000, '8', ['8']), - (0x202000, '9', ['9']), + (0x202000, '9', ['9']), # 2nd row ---------- (0x202000, '4', ['4']), (0x202000, '5', ['5']), @@ -17,7 +17,7 @@ app = { # REQUIRED dict, must be named 'app' # 3rd row ---------- (0x202000, '1', ['1']), (0x202000, '2', ['2']), - (0x202000, '3', ['3']), + (0x202000, '3', ['3']), # 4th row ---------- (0x101010, '*', ['*']), (0x800000, '0', ['0']),