behavior change: 72 frame eased followpoint, AnimationFramerate 60
P1
An osu!stable skin rendered from code. Black screen, a terminal font, phosphor green UI, combos alternating green and violet, and a cyan cursor. The name is the code for the classic green phosphor in old terminals and scopes.
Every image is drawn by gen.py with Pillow. Change a colour or a stroke width, rerun it, and the whole skin follows.
Download
Grab P1.osk from Releases and open it; osu! imports it. The release includes sounds, see Credits.
Build
Requirements: Python 3, Pillow, fontconfig (fc-match), and Terminess Nerd Font installed system wide.
python3 gen.py out/P1
Copy out/P1 into your osu! Skins folder and pick P1 in Options > Skin.
This builds the visuals only, with no sounds, so osu! uses its default sounds. To pull sounds from skins you already own:
python3 gen.py out/P1 --assets "Skins/Some Skin" --hitsounds "Skins/Other Skin" --osk P1.osk
--assetstakes every sound from that skin.--hitsoundsreplaces only the gameplay sounds (hit, slider, nightcore, combobreak) with another skin's set. Any matching sound from--assetsis removed first, in every extension and numbering, so two sets never mix.--oskalso packs the finished skin into an.osk(a zip of the skin folder).
preview.py out/P1 docs/preview.png renders the asset sheet above from any build. The gameplay loop is a danser-go replay render, cut to 10 seconds and encoded as animated WebP so it plays inline on any git host. Every frame is a keyframe (Pillow kmax=1): with inter-frame deltas, lossy WebP leaves ghost blocks where objects used to be on the black background.
Rebuild into a fresh folder and replace the old one. Hidden elements are blank @1x files, and a stale @2x left behind by a previous build would win over them.
How it is drawn
- 4x supersampling. Each element is drawn at four times its
@2xsize, then downsampled to@2xand@1x. Edges and thin rings come out smooth without a separate antialiasing pass. - White where the game tints. osu! multiplies hit circles, approach circles, input keys and song select cards by a colour at draw time. Those are drawn white or grey so the combo colour shows through unchanged. The slider ball, slider ticks and follow circle stay white: the follow circle is never tinted by stable, so all three match it.
- Hidden, not missing. Lighting, particles, combo bursts, kiai fountains, the cursor ripple and the slider tail circle are 1x1 transparent images. A missing file falls back to the default skin, so hiding takes a file.
- Palette.
#00ff00with dim tiers for the UI; saturated combo colours alternating green0,255,0and violet170,60,255; cyan40,234,242for the cursor only;#ff5555for misses only. No combo uses cyan or red, so the cursor and misses always stand out.
Limits of stable skinning
Some things a skin cannot change in osu!stable: the progress pie, the hit error bar colours, leaderboard names, and the colours the game uses for pressed input keys. Slider bodies are a dark neutral because a per combo body renders at full brightness and there is no opacity setting.
License
MIT for everything in this repository. The font is not included; Terminess Nerd Font is under the SIL Open Font License.
Credits
The sounds in the release .osk are not part of this repository and not covered by its license. Menu and interface sounds come from the Beafowl skin (skin.ini author: Garin); gameplay hitsounds come from the Stars in The Sky skin (author not listed). They are included with credit; if you are an author and want them removed, open an issue and they will be.

