I wanted to see how far PHP in WebAssembly could go. So I wrote a fan remake of Sonic the Hedgehog (Master System) entirely in PHP, about 21k lines, and made it run both natively and in the browser.
👉 Play it, no install: https://sonic.mimichat.fr (desktop and mobile)
How PHP runs in a browser
PHP 8.3 is compiled to WebAssembly with Emscripten, together with an SDL2 extension for PHP. A small C glue starts PHP (php_embed_init), runs the game, then plugs into the browser loop: on every requestAnimationFrame, one tick of the game's ReactPHP event loop.
The tricky part: ReactPHP's Loop::run() is blocking, and a browser can't allow that. So the page queues a futureTick that stops the loop right after its first turn, and the C glue then advances it one tick at a time. PHP is never shut down between frames (php_embed_shutdown() is never called): every object and SDL resource stays in memory, the whole game state lives across frames.
SDL2's Emscripten port renders to WebGL and plays sound through Web Audio. Saves go to IndexedDB (IDBFS).
One lesson learned: use one browser loop only. A second setTimeout(0) loop ran the game between frames too, saturating the main thread so that input and audio came last.
Online multiplayer, up to 6 players
Race, capture the flag, rings, deathmatch. Browsers talk directly over WebRTC; a relay written in PHP handles rooms and signaling, with coturn for difficult networks. A player on the native desktop version can join the same room through the relay. The network layer is its own library: php-wasm-network.
The website
Symfony 8.1 on FrankenPHP: live rooms, stats, faithful replays of every game, and editors for levels, tiles (drawing and collisions), sprites, sounds and music. A published level is playable in the game right away. Visitors appear live as little Sonics running across the page, through Mercure subscription events.
Try it
- Play: https://sonic.mimichat.fr
- Build a level in the editor and play it in-game
- Create a private room and send the link to a friend
Code: sonicGamePhp (game), php-wasm-sdl (PHP + SDL in WASM), php-wasm-network (networking).
It's a non-commercial fan project, Sonic belongs to SEGA. Questions about PHP in WASM are welcome in the comments!
Top comments (0)