Would be cool to create games in Panel!
I think that for any game to perform in the browser it needs to run inside the browser. The next question is really if you want to code the game in python or js. If its Python then probably your best option is to find a python game framework that works on pyodide or use PyScript with a js game engine.
According to my google searches pygame has not been ported to pyodide as of 2023-06-11. But there it can run on something called pybag.
You could also search for python game engines that can run on pyodide. For example pyxel, enpyre
To get that working with Panel my approach would be creating a ReactiveHTML component. Alternatively panel convert
your Panel application to pyodide.
You can also look at how game development has been described in Jupyter Games. Ipycanvas
Here is a proof of concept with PIXI JS.
We create a new Panel component called PixiJS
. The component will let you provide an object
which is the python code implementing the game.
The code in the object
can refer to the
-
PIXI
: the PIXI js object -
app
: A PIXI app that has already been created and shown in the component. -
data
,state
,model
,view
: The values exposed by reactive html
The component is built using Panels ReactiveHTML
and pyodide.
The code looks like.
import param
import panel as pn
from panel.reactive import ReactiveHTML
pn.extension()
RENDER_SCRIPT = """
async function main(){
let pyodide = await loadPyodide();
app = new PIXI.Application({
"autoResize": true,
})
canvas.appendChild(app.view)
resize = ()=>{app.renderer.resize(canvas.offsetWidth, canvas.offsetHeight)}
addEventListener("resize", resize);
resize()
state.app=app
window._panel_pixie_objects = {
"canvas": canvas,
"app": app,
"data": data,
"state": state,
"model": model,
"view": view,
"state": state,
}
import_panel_pixie_objects = `
from js import _panel_pixie_objects, PIXI
canvas = _panel_pixie_objects.canvas
app = _panel_pixie_objects.app
data = _panel_pixie_objects.data
state=_panel_pixie_objects.state
model=_panel_pixie_objects.model
`
script = import_panel_pixie_objects + data.object
pyodide.runPython(script);
}
main();
"""
TEMPLATE = f"""
<div id="canvas" style="height:100%;width:100%;overflow:hidden"></div>
"""
class PixiJS(ReactiveHTML):
object = param.String()
js_to_py_event = param.Parameter()
py_to_js_event = param.Parameter()
_template = TEMPLATE
__javascript__=[
"https://pixijs.download/release/pixi.js",
"https://cdn.jsdelivr.net/pyodide/v0.23.2/full/pyodide.js"
]
_scripts = {
"render": RENDER_SCRIPT
}
GAME_SCRIPT = """
from js import document, console, Object, window
from pyodide.ffi import create_proxy, to_js
import math
import random
sprite = PIXI.Sprite.from_("https://panel.holoviz.org/_images/logo_horizontal_light_theme.png")
app.stage.addChild(sprite);
elapsed = 0.0;
def update(delta):
global elapsed
elapsed += delta
py_event = data.py_to_js_event
x=y=0
if py_event:
py_event=py_event.to_py()
x=py_event.get("x", x)
y=py_event.get("y", y)
sprite.x = 100.0 + math.cos(elapsed/50.0) * 100.0 + x
sprite.y = 100.0 + math.cos(elapsed/50.0) * 100.0 + y
event = {"x": sprite.x, "y": sprite.y}
event = to_js(event)
event = Object.fromEntries(event)
data.js_to_py_event=event
update_proxy = create_proxy(update)
app.ticker.add(update_proxy);
"""
game = PixiJS(object=GAME_SCRIPT, py_to_js_event={"x": 0, "y": 0}, sizing_mode="stretch_width", height=500, styles={"background": "gray"})
pn.template.FastListTemplate(
title="Who is playing games with Panel and PIXI js?",
main=[pn.Column(game, game.param.py_to_js_event, game.param.js_to_py_event)],
).servable()
Serve the app with
panel serve script.py
Please note, I cannot get the communication from the client to the server (via js_to_py_event
) working and I can find no error message indicating why.
Next Steps
- Get communication from client to server working. The
js_to_py_event
parameter does not seem to get a dictionary with the spritex
andy
values. - Understand what are python and what are js objects and learn how to use/ convert them.
- Figure out if its better to use
pyscript
for this use case thanpyodide
. Maybe use micropython instead of pyodide to load faster. - Implement real game. Maybe use ChatGPT to convert some PIXI js examples to Python.
- Improve the developer experience
Thank you so much for exploring this!
I’ve been teaching my little cousin how to code in Python with pygame and we ended up creating a pretty cool game that I’d love to share somehow; maybe we can translate it to PixiJS.