diff --git a/badge/apps/fireplace/README.md b/badge/apps/fireplace/README.md new file mode 100644 index 0000000..327d02b --- /dev/null +++ b/badge/apps/fireplace/README.md @@ -0,0 +1,47 @@ +# 🔥 Fireplace + +A cosy animated fireplace app for the GitHub Universe 2025 badge. The speed can be adjusted to the user's preference. + + + +This app was inspired by the fireplace from [Lenny's Podcast](https://www.lennysnewsletter.com/podcast) quietly running in the background. + + + +## Controls + +| Button | Action | +|--------|--------| +| **↑ UP** | Speed up (−50ms per press, min 50ms/frame) | +| **↓ DOWN** | Slow down (+50ms per press, max 1000ms/frame) | +| **A / B / C** | Reset to default speed | +| **HOME** | Return to menu | + +The current frame duration is displayed briefly at the bottom of the screen whenever the speed is changed. + +## Installation + +Copy the `fireplace/` folder to `/system/apps/fireplace/` on your badge (put it into disk mode first by double-pressing RESET while connected via USB-C). + +``` +fireplace/ +├── __init__.py # App code +├── icon.png # Menu icon (24x24) +├── assets/ # Source images +│ ├── fireplace.gif # Original source GIF +│ ├── fireplace_badge.jpg # Badge photo +│ └── lenny_fireplace.jpg # Lenny photo +└── frames/ # Extracted PNG frames (frame_0000.png … frame_0019.png) +``` + +## Running in the Simulator + +```bash +python simulator/badge_simulator.py badge/apps/fireplace -C badge --scale 4 +``` + +## Animation Details + +- **Source**: [Tenor GIF](https://tenor.com/en-CA/view/seninle-a%C5%9Fkom-yalanmo%C5%9F-gif-27389050) +- **Frames**: 20 PNGs at 160×120 pixels +- **Default speed**: 100ms per frame (10 fps) diff --git a/badge/apps/fireplace/__init__.py b/badge/apps/fireplace/__init__.py new file mode 100644 index 0000000..71c2422 --- /dev/null +++ b/badge/apps/fireplace/__init__.py @@ -0,0 +1,83 @@ +import sys +import os + +sys.path.insert(0, "/system/apps/fireplace") +os.chdir("/system/apps/fireplace") + +from badgeware import screen, io, run, brushes, PixelFont, shapes + +FRAME_COUNT = 20 +DEFAULT_DURATION = 100 # ms per frame +MIN_DURATION = 50 +MAX_DURATION = 1000 +SPEED_STEP = 50 +LABEL_TIMEOUT = 1500 # ms to show the label after a speed change + +_current_frame = 0 +_last_tick = None +_frame_duration = DEFAULT_DURATION +_label_until = 0 # ticks timestamp until which to show the label +_needs_redraw = True # reload frame when it advances or label expires + +_font = None +_label_brush = None +_bg_brush = None + + +def init(): + global _font, _label_brush, _bg_brush + _font = PixelFont.load("/system/assets/fonts/nope.ppf") + screen.font = _font + _label_brush = brushes.color(255, 255, 255, 200) + _bg_brush = brushes.color(0, 0, 0, 150) + + +def update(): + global _current_frame, _last_tick, _frame_duration, _label_until, _needs_redraw + + if _last_tick is None: + _last_tick = io.ticks + + # Speed up + if io.BUTTON_UP in io.pressed: + _frame_duration = max(MIN_DURATION, _frame_duration - SPEED_STEP) + _label_until = io.ticks + LABEL_TIMEOUT + + # Slow down + if io.BUTTON_DOWN in io.pressed: + _frame_duration = min(MAX_DURATION, _frame_duration + SPEED_STEP) + _label_until = io.ticks + LABEL_TIMEOUT + + # Any of A, B, C resets to default + if io.BUTTON_A in io.pressed or io.BUTTON_B in io.pressed or io.BUTTON_C in io.pressed: + _frame_duration = DEFAULT_DURATION + _label_until = io.ticks + LABEL_TIMEOUT + + # Advance frame + if io.ticks - _last_tick >= _frame_duration: + _current_frame = (_current_frame + 1) % FRAME_COUNT + _last_tick = io.ticks + _needs_redraw = True + + showing_label = io.ticks < _label_until + + # Only reload the PNG when the frame changed or the label just cleared + if _needs_redraw: + screen.load_into(f"frames/frame_{_current_frame:04d}.png") + _needs_redraw = showing_label # stay dirty while label is visible + + # Show speed label if recently changed + if showing_label: + label = f"{_frame_duration}ms/frame" + w, h = screen.measure_text(label) + pad = 4 + x = (screen.width - w) // 2 + y = screen.height - h - pad * 2 + screen.brush = _bg_brush + screen.draw(shapes.rectangle(x - pad, y - pad, w + pad * 2, h + pad * 2)) + screen.brush = _label_brush + screen.text(label, x, y) + + +if __name__ == "__main__": + run(update, init=init) diff --git a/badge/apps/fireplace/assets/fireplace.gif b/badge/apps/fireplace/assets/fireplace.gif new file mode 100644 index 0000000..c91503e Binary files /dev/null and b/badge/apps/fireplace/assets/fireplace.gif differ diff --git a/badge/apps/fireplace/assets/fireplace_badge.jpg b/badge/apps/fireplace/assets/fireplace_badge.jpg new file mode 100644 index 0000000..aeccfee Binary files /dev/null and b/badge/apps/fireplace/assets/fireplace_badge.jpg differ diff --git a/badge/apps/fireplace/assets/lenny_fireplace.jpg b/badge/apps/fireplace/assets/lenny_fireplace.jpg new file mode 100644 index 0000000..ec921eb Binary files /dev/null and b/badge/apps/fireplace/assets/lenny_fireplace.jpg differ diff --git a/badge/apps/fireplace/frames/frame_0000.png b/badge/apps/fireplace/frames/frame_0000.png new file mode 100644 index 0000000..394c641 Binary files /dev/null and b/badge/apps/fireplace/frames/frame_0000.png differ diff --git a/badge/apps/fireplace/frames/frame_0001.png b/badge/apps/fireplace/frames/frame_0001.png new file mode 100644 index 0000000..51b78fe Binary files /dev/null and b/badge/apps/fireplace/frames/frame_0001.png differ diff --git a/badge/apps/fireplace/frames/frame_0002.png b/badge/apps/fireplace/frames/frame_0002.png new file mode 100644 index 0000000..cde2458 Binary files /dev/null and b/badge/apps/fireplace/frames/frame_0002.png differ diff --git a/badge/apps/fireplace/frames/frame_0003.png b/badge/apps/fireplace/frames/frame_0003.png new file mode 100644 index 0000000..bf1ad11 Binary files /dev/null and b/badge/apps/fireplace/frames/frame_0003.png differ diff --git a/badge/apps/fireplace/frames/frame_0004.png b/badge/apps/fireplace/frames/frame_0004.png new file mode 100644 index 0000000..1980d04 Binary files /dev/null and b/badge/apps/fireplace/frames/frame_0004.png differ diff --git a/badge/apps/fireplace/frames/frame_0005.png b/badge/apps/fireplace/frames/frame_0005.png new file mode 100644 index 0000000..407a6cc Binary files /dev/null and b/badge/apps/fireplace/frames/frame_0005.png differ diff --git a/badge/apps/fireplace/frames/frame_0006.png b/badge/apps/fireplace/frames/frame_0006.png new file mode 100644 index 0000000..bf39690 Binary files /dev/null and b/badge/apps/fireplace/frames/frame_0006.png differ diff --git a/badge/apps/fireplace/frames/frame_0007.png b/badge/apps/fireplace/frames/frame_0007.png new file mode 100644 index 0000000..09f95eb Binary files /dev/null and b/badge/apps/fireplace/frames/frame_0007.png differ diff --git a/badge/apps/fireplace/frames/frame_0008.png b/badge/apps/fireplace/frames/frame_0008.png new file mode 100644 index 0000000..b79eb31 Binary files /dev/null and b/badge/apps/fireplace/frames/frame_0008.png differ diff --git a/badge/apps/fireplace/frames/frame_0009.png b/badge/apps/fireplace/frames/frame_0009.png new file mode 100644 index 0000000..e4aac6f Binary files /dev/null and b/badge/apps/fireplace/frames/frame_0009.png differ diff --git a/badge/apps/fireplace/frames/frame_0010.png b/badge/apps/fireplace/frames/frame_0010.png new file mode 100644 index 0000000..6adebf1 Binary files /dev/null and b/badge/apps/fireplace/frames/frame_0010.png differ diff --git a/badge/apps/fireplace/frames/frame_0011.png b/badge/apps/fireplace/frames/frame_0011.png new file mode 100644 index 0000000..76b159c Binary files /dev/null and b/badge/apps/fireplace/frames/frame_0011.png differ diff --git a/badge/apps/fireplace/frames/frame_0012.png b/badge/apps/fireplace/frames/frame_0012.png new file mode 100644 index 0000000..ce434fd Binary files /dev/null and b/badge/apps/fireplace/frames/frame_0012.png differ diff --git a/badge/apps/fireplace/frames/frame_0013.png b/badge/apps/fireplace/frames/frame_0013.png new file mode 100644 index 0000000..384c839 Binary files /dev/null and b/badge/apps/fireplace/frames/frame_0013.png differ diff --git a/badge/apps/fireplace/frames/frame_0014.png b/badge/apps/fireplace/frames/frame_0014.png new file mode 100644 index 0000000..8ae609c Binary files /dev/null and b/badge/apps/fireplace/frames/frame_0014.png differ diff --git a/badge/apps/fireplace/frames/frame_0015.png b/badge/apps/fireplace/frames/frame_0015.png new file mode 100644 index 0000000..ac36869 Binary files /dev/null and b/badge/apps/fireplace/frames/frame_0015.png differ diff --git a/badge/apps/fireplace/frames/frame_0016.png b/badge/apps/fireplace/frames/frame_0016.png new file mode 100644 index 0000000..805a7fb Binary files /dev/null and b/badge/apps/fireplace/frames/frame_0016.png differ diff --git a/badge/apps/fireplace/frames/frame_0017.png b/badge/apps/fireplace/frames/frame_0017.png new file mode 100644 index 0000000..c8fdeb9 Binary files /dev/null and b/badge/apps/fireplace/frames/frame_0017.png differ diff --git a/badge/apps/fireplace/frames/frame_0018.png b/badge/apps/fireplace/frames/frame_0018.png new file mode 100644 index 0000000..e8137f8 Binary files /dev/null and b/badge/apps/fireplace/frames/frame_0018.png differ diff --git a/badge/apps/fireplace/frames/frame_0019.png b/badge/apps/fireplace/frames/frame_0019.png new file mode 100644 index 0000000..dde292c Binary files /dev/null and b/badge/apps/fireplace/frames/frame_0019.png differ diff --git a/badge/apps/fireplace/icon.png b/badge/apps/fireplace/icon.png new file mode 100644 index 0000000..e96cd6e Binary files /dev/null and b/badge/apps/fireplace/icon.png differ