This project now supports running in web browsers using Pygbag and WebAssembly. The game runs entirely client-side with no server required.
Pygbag packages Python/Pygame applications to run in web browsers using:
- WebAssembly: Compiles Python to run in browsers
- Emscripten: The compilation toolchain
- AsyncIO: Non-blocking game loop for browser compatibility
The main game loop now uses async/await to yield control to the browser's event loop:
async def main():
# Game initialization
await game_loop.draw()
# In GameLoop.draw():
while self.is_alive:
# Game logic
pygame.display.flip()
await asyncio.sleep(0) # Critical: yields to browsermain.py(lowercase) is the Pygbag entry point- Maintains compatibility with desktop Python execution
- Assets must be in the same directory as main.py
- Pygbag bundles all files in the project directory
source venv/bin/activate
pip install pygbagQuick test server:
pygbag .This starts a local server at http://localhost:8000
Build for deployment:
pygbag --build .Output: build/web/ directory contains deployable files
Custom build script:
./build_web.sh-
Build the project:
./build_web.sh
-
Create a
gh-pagesbranch:git checkout -b gh-pages cp -r build/web/* . git add . git commit -m "Deploy to GitHub Pages" git push origin gh-pages
-
Enable GitHub Pages in repository settings
- Go to Settings → Pages
- Source: gh-pages branch
- Your game will be at:
https://username.github.io/repo-name/
-
Build the project:
./build_web.sh
-
Create a ZIP of the build/web directory:
cd build/web zip -r game.zip *
-
Upload to itch.io:
- Create new project on itch.io
- Set "Kind of project" to HTML
- Upload game.zip
- Check "This file will be played in the browser"
- Set embed options (800x600 recommended)
-
Build the project:
./build_web.sh
-
Deploy the
build/webdirectory using their CLI or web interface
- Build the project
- Copy
build/web/*to your web server - Ensure proper MIME types are set:
.wasm:application/wasm.js:application/javascript
python -m http.server 8000 --directory build/webOpen: http://localhost:8000
pygbag --dev .Includes live reload on file changes
Supported Browsers:
- ✅ Chrome/Chromium (recommended)
- ✅ Firefox
- ✅ Edge
- ✅ Safari (macOS/iOS)
- ✅ Opera
Requirements:
- WebAssembly support (all modern browsers)
- JavaScript enabled
- SharedArrayBuffer support (for audio)
Note: Some older browsers may have limited audio support.
- Desktop: ~60 FPS typical
- Browser: 30-60 FPS depending on device
- Use
await asyncio.sleep(0)in main loop - Minimize file sizes (compress images/audio)
- Avoid blocking operations
- Use pygame optimizations (convert_alpha, etc.)
- Check browser console for errors (F12)
- Verify all assets are in the project directory
- Ensure CORS headers if self-hosting
- Browser audio requires user interaction first
- Some browsers block autoplay
- Check SharedArrayBuffer support
- Reduce FPS constant if needed
- Optimize sprite rendering
- Check browser's hardware acceleration
- Verify pygame.display.flip() is called
- Check await asyncio.sleep(0) is in game loop
- Ensure assets load correctly
build/web/
├── index.html # Main HTML file
├── pythons.js # Pygbag loader
├── <project>.data # Game assets
├── <project>.js # Compiled game
├── <project>.wasm # WebAssembly binary
└── ... # Additional support files
- Develop: Code and test with
python main.py - Test Web: Quick test with
pygbag . - Build: Production build with
./build_web.sh - Deploy: Upload build/web/* to hosting
- File I/O: Limited compared to desktop
- Audio: May have latency in some browsers
- Performance: Slightly slower than native
- Threading: Limited support
- Some Pygame features: Not all are supported in browser
For Pygbag-specific issues, see:
For game-specific issues, see project repository.