dcc4757f 2026-04-09 Pavel Safronov | 1 | # Bubbles |
| 2 | |
| 3 | Your phone is a glass of water. |
| 4 | |
| 5 | Tilt to slosh. Tap to drop things in. Some float. Some sink. |
| 6 | |
c71d2317 2026-10-27 Pavel Safronov | 7 | **Live demo:** https://apps.fuzzyworld.net/bubbles/ |
dcc4757f 2026-04-09 Pavel Safronov | 8 | |
c71d2317 2026-10-27 Pavel Safronov | 9 | **Repository:** https://code.fuzzyworld.net/bubbles/ (`git clone https://code.fuzzyworld.net/bubbles.git`) |
dcc4757f 2026-04-09 Pavel Safronov | 10 | |
| 11 | --- |
| 12 | |
| 13 | ## What it does |
| 14 | |
| 15 | | Action | Result | |
| 16 | | --------------------- | -------------------------------------------- | |
| 17 | | Tilt phone left/right | Water sloshes toward the low side | |
| 18 | | Tilt past ~45ยฐ | Water spills over the rim (permanently lost) | |
| 19 | | Tap anywhere | A random object drops into the water | |
| 20 | | Desktop | Move mouse left/right to simulate tilt | |
| 21 | |
| 22 | ### Objects |
| 23 | |
| 24 | | Icon | Density | Behaviour | |
| 25 | | ----------- | ------- | -------------------------- | |
| 26 | | ๐ Ping pong | 0.10 | Bobs wildly on the surface | |
| 27 | | ๐ฆ Duck | 0.50 | Floats high | |
| 28 | | ๐ Apple | 0.80 | Floats | |
| 29 | | ๐ Lemon | 0.85 | Floats | |
| 30 | | ๐ง Ice | 0.92 | Barely floats | |
| 31 | | ๐ Fish | 1.05 | Barely sinks | |
| 32 | | ๐ชจ Rock | 2.60 | Sinks | |
| 33 | | ๐ Gem | 3.50 | Sinks | |
| 34 | | โ Anchor | 7.50 | Sinks fast | |
| 35 | | ๐ฉ Bolt | 7.80 | Sinks fast | |
| 36 | |
| 37 | Max 12 objects at a time โ the oldest is removed when you add a 13th. |
| 38 | |
| 39 | --- |
| 40 | |
| 41 | ## Tech |
| 42 | |
| 43 | - TypeScript + Canvas 2D API (no framework, no WebGL) |
| 44 | - Vite for bundling |
| 45 | - pnpm for package management |
c71d2317 2026-10-27 Pavel Safronov | 46 | - Static hosting at apps.fuzzyworld.net (no server) |
dcc4757f 2026-04-09 Pavel Safronov | 47 | |
| 48 | Physics: |
| 49 | - 1-D column wave simulation (80 columns, spring-coupled) |
| 50 | - Buoyancy via submerged fraction of circle cross-section |
| 51 | - Elastic damped circle vs. circle + wall collisions |
| 52 | - `DeviceOrientationEvent` for real tilt; mouse fallback on desktop |
| 53 | |
| 54 | --- |
| 55 | |
| 56 | ## Development |
| 57 | |
| 58 | ```sh |
| 59 | # Install dependencies |
| 60 | pnpm install |
| 61 | |
| 62 | # Generate favicons and og-image from wind.png |
| 63 | pnpm gen-assets |
| 64 | |
| 65 | # Start dev server |
| 66 | pnpm dev |
| 67 | |
| 68 | # Type-check + production build |
| 69 | pnpm build |
| 70 | ``` |
| 71 | |
c71d2317 2026-10-27 Pavel Safronov | 72 | Output goes to `dist/`. |
dcc4757f 2026-04-09 Pavel Safronov | 73 | |
| 74 | --- |
| 75 | |
| 76 | ## Deploy |
| 77 | |
c71d2317 2026-10-27 Pavel Safronov | 78 | ```bash |
| 79 | pnpm run deploy |
| 80 | ``` |
| 81 | |
| 82 | `fw deploy` (from [fuzzyworld-tools](https://code.fuzzyworld.net/fuzzyworld-tools/)) builds a fresh clone of `main`: |
dcc4757f 2026-04-09 Pavel Safronov | 83 | |
| 84 | ``` |
c71d2317 2026-10-27 Pavel Safronov | 85 | pnpm install โ pnpm gen-assets โ pnpm build โ upload dist/ |
dcc4757f 2026-04-09 Pavel Safronov | 86 | ``` |
| 87 | |
c71d2317 2026-10-27 Pavel Safronov | 88 | and publishes it at https://apps.fuzzyworld.net/bubbles/ |
dcc4757f 2026-04-09 Pavel Safronov | 89 | |
| 90 | --- |
| 91 | |
| 92 | ## Attribution |
| 93 | |
| 94 | Wind icon by [Icongeek26](https://www.flaticon.com/authors/icongeek26) from [Flaticon](https://www.flaticon.com/). |