Play it here (free, in the browser, 1-4 players): https://playgama.ai/play/nuxkra3i4xiowc
Moth Party is entered in @playgama's **Player Two Found* challenge for games you play with the friend sitting next to you. #PlayerTwoFound*
Moth Party is a party game where each player gets exactly one button. Hold it and your moth flies forward. Let go and it spins in place. You steer by timing your release: let go, wait until the moth faces where you want to go, then hold again.
That's the whole control scheme, so four people can share one keyboard (Q / P / Z / M) or one phone (each player holds a corner). Grab glowing sparks, ram rivals to knock theirs loose, and get away from the lamp when it flickers. Rounds last 45 seconds, and the first moth to win 3 rounds takes the match. Empty seats are filled by CPU moths, so it works solo too.
The fun part was making one button feel like enough. Some notes on how it works, all from the ~200-line simulation file.
1. The physics: two states, one gravity
Each moth is always doing exactly one of two things:
if (held) { m.vx += Math.cos(m.a) * THRUST * dt; m.vy += Math.sin(m.a) * THRUST * dt; }
else { m.a += SPIN * dt; } // 4.2 rad/s, about 1.5 s per full turn
On top of that, a light pull toward the lamp at the centre, exponential drag and a speed cap. The pull matters most. If you don't hold the button, you drift into the light, which is exactly what a moth would do. It also keeps everyone near the middle of the arena, where the collisions happen.
The arena wall reflects you at about 70% of your incoming speed, so a hard wall hit throws you back into the fight instead of leaving you stuck at the edge.
2. Who hit whom?
When two moths overlap, they swap momentum along the collision normal (a bit bouncier than elastic, 1.15x, because bouncy is funnier). The interesting question is blame. If the relative speed is above a threshold, the moth that was moving into the hit faster is the hitter, and the other one is knocked:
const hitter = va > -vb ? A : B, victim = hitter === A ? B : A;
const lost = victim.carry > 0 ? Math.max(1, Math.ceil(victim.carry / 3)) : 0;
The victim drops a third of their sparks (at least one) and is stunned for 0.45 s. Dropped sparks can't be re-grabbed for 0.35 s, so the hitter can't just vacuum them up. Anyone nearby gets a shot at them. That one rule creates most of the "NOOO" moments.
3. The lamp is the third player
The lamp cycles calm → warn (it flickers) → flare. Any moth inside the flare radius loses half its sparks and is blasted outward. So the safest place to collect sparks is also the most dangerous place to hold them. The richer you are, the more the flicker matters.
4. A CPU that only has one button too
The CPU moths play under the same rule: they only decide hold or release each frame. The bot:
- picks a target: run outward if the lamp is about to flare, otherwise the nearest spark, or a rich rival (3+ sparks) if one is close enough to be worth ramming, aiming a little ahead of where they're going;
- holds while it's facing the target within a cone, and releases to spin otherwise.
Difficulty (sleepy / buzzing / feral) is just two numbers: random aim jitter and a wider "close enough" cone. A sleepy moth over-rotates and wobbles, while a feral one lines up and rams you.
5. Testing a party game with no humans
node test.js runs 40 all-CPU matches at 60 Hz with mixed skill levels and checks that nothing is NaN, no moth escapes the arena, every match ends with one champion, and no seat is favoured. Latest run:
{"grab":14475,"bump":3852,"burn":454,"rounds":217,"winsBy":[10,9,12,9],"ties":14}
ALL PASS grabs/round 66.7 bumps/round 17.8 burns/round 2.1 rounds/match 5.4
Those rates are also the design dials. If bumps per round drop under 2, the game feels like solo spark-collecting. If burns drop under 0.5, the lamp stops being scary. The test fails in both cases, so a tuning change can't quietly kill the party.
Try it
- 1-4 players, one button each (Q / P / Z / M, or hold a screen corner on mobile)
- Empty seats = CPU moths (sleepy / buzzing / feral)
- ▶ https://playgama.ai/play/nuxkra3i4xiowc
Best with friends on one laptop. Tell me who ended up as the villain.
AI disclosure: the game's code was written with an AI coding assistant (Claude). This post was also written by an AI agent working on my behalf (the facts, numbers and code snippets are from the game's source and its test run). Art is drawn on canvas in code and sound is WebAudio synthesis. No downloaded assets.
Top comments (0)