pygbag
is not found. What should I do?”On some platforms, pygbag is not included in the PATH environment variable, so use python3 -m pygbag
instead of just pygbag, python -m pygbag
if you don’t also have Python 2 installed or py -m pygbag
on Windows platforms. (Make sure to use Python downloaded from python.org, not Microsoft Store)
This is the default, because most browsers will not start any music until user interacts with the game.
Append --ume_block=0
to your command and your game will start without user input.
SDL2 is hard realtime, so sometimes the game asks too much from average devices and is a bit late on frame. Because of this, sound effects are distorted. To solve this, upgrade to 0.1.5 or use external Javascript sound manager.
Possible other solution: replace sdl2_audio by openal, PR welcomed…
Make sure you have removed all debug print()
calls, as printing to the terminal or console reduces performance a lot.
Add everything you need alongside main.py
, including hand-picked stdlib modules. Pygbag does not include Python’s entire standard library in order to keep a small build size for mobile connections. You can find extra stdlib modules in pythonx.xx.x.zip
from python.org matching pygbag python version (3.12 is the default). You can change python stdlib version adding --PYBUILD 3.13
.
Add everything you need alongside main.py
, including binary modules. They must be compatiable with the Python version loaded by Pygbag in the web page: this may not be the python version you used to run pygbag - when they are not wasm abi3 modules. Sometimes you may have to wait for the maintainer to provide a build, build your own with python-wasm-sdk, extract a wheel from or pyodide’s build, or maybe just ask/offer a link to it here.
It is possible to access FTDI (and clones) USB serial ports, but it is very experimental. You need to remove the driver using the serial port for that (rmmod
or zadig
).
if sys.platform == "emscripten":
pass
if 'wasm' in __import__('platform').machine():
pass
import platform
def on_upload_files(ev):
print("on_upload_files", ev)
if ev.mimetype.startswith('image/'):
# we can display that
shell.display(ev.text)
platform.EventTarget.addEventListener(None, "upload", on_upload_files )
platform.window.dlg_multifile.hidden = false
import platform
from pathlib import Path
cdn = Path("https://cdn.jsdelivr.net/pyodide/dev/full")
async def main():
async with platform.fopen( cdn / "repodata.json", "r") as textfile:
print( len( textfile.read() ) )
asyncio.run(main())
from pathlib import Path
cdn = Path("https://cdn.jsdelivr.net/pyodide/dev/full")
import urllib.request
outfile, _ = urllib.request.urlretrieve(cdn / "repodata.json", outfile)
# or just:
# outfile = "/tmp/pip.json"
# shell.wget(f"-O{outfile}", cdn / "repodata.json")
import json
with open(outfile) as data:
repo = json.loads( data.read() )
print( json.dumps(repo["packages"], sort_keys=True, indent=4) )
implemented, event based, TODO sample
Python files can still be created normally and will appear in the browser’s filesystem. They can then be downloaded from the browser’s filesystem to a user’s filesystem with platform.window.MM.download(filepath)
.
import sys, platform
with open("file.txt", "w") as f:
f.write("newly created example file")
if sys.platform == "emscripten":
platform.window.MM.download("file.txt")
platform.window.MM.download("file.txt")
is code taken from the debug REPL’s shell implementation. Read about the debug REPL here.
not implemented, TODO : https://developer.mozilla.org/en-US/docs/Web/API/FileSystemDirectoryHandle
import asyncio
async def main():
color = await input("what is your favorite colour ? ")
print(f" {color=} ")
asyncio.run(main())
do not forget the leading #!pgzrun !
#!pgzrun
WIDTH = 800
HEIGHT = 600
class ship:
x = 370
y = 550
@classmethod
def update(cls):
screen.draw.filled_circle( (cls.x, cls.y), 10, (128,128,128))
def update():
if keyboard.left:
ship.x = ship.x - 5
if keyboard.right:
ship.x = ship.x + 5
def draw():
screen.fill((80,0,70))
ship.update()
import pygame
import sys
screen = pygame.display.set_mode([1024, 600], pygame.SRCALPHA, 32)
screen.set_colorkey( (0,0,0,0), pygame.RLEACCEL )
screen.fill( (0,0,0,0) )
if (web := sys.platform in ('emscripten','wasi')):
from platform import window
async def main():
global ctx, web
rng = 10 # resolution of progress bar
slot = (1024-200)/rng
for i in range(rng):
marginx = 100
marginy = 200
pygame.draw.rect(screen,(10,10,10),( marginx-10, marginy-10, (rng*slot)+20, 110 ) )
pygame.draw.rect(screen,(0,255,0), ( marginx, marginy, (1+i)*slot, 90) )
pygame.display.update()
if web:
window.chromakey(None, *screen.get_colorkey(), 30)
await asyncio.sleep(1)
asyncio.run(main())
if __import__("sys").platform == "emscripten":
from platform import window
backup :
window.localStorage.setItem("mygame", str(myvalue) )
restore :
myvalue = window.localStorage.getItem("mygame")
erase :
keys = []
for i in range(window.localStorage.length):
keys.append(window.localStorage.key(i))
while keys: window.localStorage.removeItem(keys.pop())
import sys
import platform
# document may not exist on non-emscripten platforms
if sys.platform == "emscripten":
platform.document.body.style.background = "#404040"
TODO, drag/drop events, gestures.
TODO, pygame interface is not finished.
TODO
TODO