You can ship a Python game to Wavedash by running CPython in the browser with Pyodide. There's no build step — Pyodide loads from a CDN, reads your .py file at runtime, and exposes the browser globals (document, window, and Wavedash) to Python code through the js module.
Setup
Create a web/ folder with an index.html that boots Pyodide and a main.py with your game.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>My Python Game</title>
<style>
html, body { margin: 0; height: 100%; background: #0a0a0a; }
#gameCanvas { width: 100%; height: 100%; display: block; }
</style>
</head>
<body>
<canvas id="gameCanvas"></canvas>
<script type="module">
import { loadPyodide } from "https://cdn.jsdelivr.net/pyodide/v0.29.3/full/pyodide.mjs";
const pyodide = await loadPyodide({
indexURL: "https://cdn.jsdelivr.net/pyodide/v0.29.3/full/",
});
const code = await fetch("./main.py").then((r) => r.text());
await pyodide.runPythonAsync(code);
</script>
</body>
</html>
SDK integration
Inside your main.py, import Wavedash from the js module. Use Pyodide's to_js helper when you need to pass Python dicts (SDK config, etc.) that JavaScript sees as real objects.
Calling Wavedash.init() is required. Your game stays hidden behind the Wavedash loading screen until you do. Call it once your game is ready to play.
from js import Wavedash, document, window
from pyodide.ffi import to_js
canvas = document.getElementById("gameCanvas")
ctx = canvas.getContext("2d")
def game_loop(now):
# update + draw
window.requestAnimationFrame(game_loop_proxy)
# ...set up input handlers, kick off the loop...
Wavedash.updateLoadProgressZeroToOne(1.0)
Wavedash.init(to_js({"debug": True}))
All SDK methods work through this same bridge — Wavedash.setAchievement("first_win", True), Wavedash.requestStats(), and so on. See SDK setup and Functions reference for the full list.
wavedash.toml
game_id = "YOUR_GAME_ID_HERE"
upload_dir = "./web"
entrypoint = "index.html"
Pyodide is about 10 MB of WebAssembly plus standard-library bundles. It's great for prototypes and turn-based games, but if you're targeting 60fps action, budget load time carefully and use updateLoadProgressZeroToOne to keep the player oriented while Pyodide boots.