8000 Introducing <script type="py-game"> · pyscript/pyscript@5490b67 · GitHub
[go: up one dir, main page]

Skip to content

Commit 5490b67

Browse files
committed
Introducing <script type="py-game">
1 parent d143b22 commit 5490b67

File tree

12 files changed

+520
-3
lines changed

12 files changed

+520
-3
lines changed

core/src/config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ const badURL = (url, expected = "") => {
2525
* @param {string?} type the optional type to enforce
2626
* @returns {{json: boolean, toml: boolean, text: string}}
2727
*/
28-
const configDetails = async (config, type) => {
28+
export const configDetails = async (config, type) => {
2929
let text = config?.trim();
3030
// we only support an object as root config
3131
let url = "",

core/src/core.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ export {
104104
export const offline_interpreter = (config) =>
105105
config?.interpreter && relative_url(config.interpreter);
106106

107-
const hooked = new Map();
107+
export const hooked = new Map();
108108

109109
for (const [TYPE, interpreter] of TYPES) {
110110
// avoid any dance if the module already landed

core/src/plugins.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ export default {
2525
/* webpackIgnore: true */
2626
"./plugins/py-editor.js"
2727
),
28+
["py-game"]: () =>
29+
import(
30+
/* webpackIgnore: true */
31+
"./plugins/py-game.js"
32+
),
2833
["py-terminal"]: () =>
2934
import(
3035
/* webpackIgnore: true */

core/src/plugins/py-game.js

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { dedent, define } from 'polyscript/exports';
2+
3+
import { stdlib } from '../core.js';
4+
import { configDetails } from '../config.js';
5+
import { getText } from '../fetch.js';
6+
7+
const hooks = {
8+
main: {
9+
onReady: async (wrap, script) => {
10+
if (script.hasAttribute('config')) {
11+
const value = script.getAttribute('config');
12+
const { json, toml, text } = configDetails(value);
13+
let config = {};
14+
if (json)
15+
config = JSON.parse(text);
16+
else if (toml) {
17+
const { parse } = await import(
18+
/* webpackIgnore: true */ "../3rd-party/toml.js"
19+
);
20+
config = parse(text);
21+
}
22+
if (config.packages) {
23+
const micropip = wrap.interpreter.pyimport('micropip');
24+
await micropip.install(config.packages, { keep_going: true });
25+
micropip.destroy();
26+
}
27+
}
28+
29+
wrap.interpreter.registerJsModule("_pyscript", {
30+
PyWorker() {
31+
throw new Error('Unable to use PyWorker in py-game scripts');
32+
},
33+
js_import: (...urls) => Promise.all(urls.map((url) => import(url))),
34+
get target() {
35+
return script.id;
36+
},
37+
});
38+
39+
await wrap.interpreter.runPythonAsync(stdlib);
40+
41+
let code = dedent(script.textContent);
42+
if (script.src)
43+
code = await fetch(script.src).then(getText);
44+
45+
const target = script.getAttribute('target') || 'canvas';
46+
const canvas = document.getElementById(target);
47+
wrap.interpreter.canvas.setCanvas2D(canvas);
48+
await wrap.interpreter.runPythonAsync(code);
49+
},
50+
},
51+
};
52+
53+
define('py-game', {
54+
config: { packages: ['pygame-ce'] },
55+
configURL: new URL('./config.txt', location.href).href,
56+
interpreter: 'pyodide',
57+
env: 'py-game',
58+
hooks,
59+
});

core/tests/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,5 @@
1414
a:hover { opacity: 1; }
1515
</style>
1616
</head>
17-
<body><ul><li><strong><span>javascript</span></strong><ul><li><a href="./javascript/async-listener.html">async-listener<small>.html</small></a></li><li><a href="./javascript/config-url.html">config-url<small>.html</small></a></li><li><a href="./javascript/config_type.html">config_type<small>.html</small></a></li><li><strong><a href="./javascript/fetch/index.html">fetch</a></strong></li><li><a href="./javascript/ffi.html">ffi<small>.html</small></a></li><li><a href="./javascript/hooks.html">hooks<small>.html</small></a></li><li><strong><a href="./javascript/issue-2093/index.html">issue-2093</a></strong></li><li><a href="./javascript/js-storage.html">js-storage<small>.html</small></a></li><li><a href="./javascript/js_modules.html">js_modules<small>.html</small></a></li><li><strong><a href="./javascript/loader/index.html">loader</a></strong></li><li><a href="./javascript/mpy-error.html">mpy-error<small>.html</small></a></li><li><a href="./javascript/mpy-no-error.html">mpy-no-error<small>.html</small></a></li><li><a href="./javascript/mpy.html">mpy<small>.html</small></a></li><li><a href="./javascript/py-terminal-main.html">py-terminal-main<small>.html</small></a></li><li><a href="./javascript/py-terminal-worker.html">py-terminal-worker<small>.html</small></a></li><li><a href="./javascript/py-terminal.html">py-terminal<small>.html</small></a></li><li><a href="./javascript/py-terminals.html">py-terminals<small>.html</small></a></li><li><strong><a href="./javascript/pyodide-cache/index.html">pyodide-cache</a></strong></li><li><strong><a href="./javascript/pyodide-lockfile/index.html">pyodide-lockfile</a></strong></li><li><a href="./javascript/storage.html">storage<small>.html</small></a></li><li><strong><span>workers</span></strong><ul><li><strong><a href="./javascript/workers/create_named/index.html">create_named</a></strong></li><li><strong><a href="./javascript/workers/mpy/index.html">mpy</a></strong></li><li><strong><a href="./javascript/workers/py/index.html">py</a></strong></li></ul></li></ul></li><li><strong><a href="./manual/index.html">manual</a></strong><ul><li><a href="./manual/all-done.html">all-done<small>.html</small></a></li><li><a href="./manual/async.html">async<small>.html</small></a></li><li><a href="./manual/camera.html">camera<small>.html</small></a></li><li><a href="./manual/click.html">click<small>.html</small></a></li><li><a href="./manual/code-a-part.html">code-a-part<small>.html</small></a></li><li><a href="./manual/combo.html">combo<small>.html</small></a></li><li><a href="./manual/config.html">config<small>.html</small></a></li><li><a href="./manual/create-element.html">create-element<small>.html</small></a></li><li><a href="./manual/dialog.html">dialog<small>.html</small></a></li><li><a href="./manual/display.html">display<small>.html</small></a></li><li><strong><a href="./manual/donkey/index.html">donkey</a></strong></li><li><a href="./manual/emoji.html">emoji<small>.html</small></a></li><li><a href="./manual/error.html">error<small>.html</small></a></li><li><a href="./manual/html-decode.html">html-decode<small>.html</small></a></li><li><a href="./manual/input.html">input<small>.html</small></a></li><li><a href="./manual/interpreter.html">interpreter<small>.html</small></a></li><li><strong><a href="./manual/issue-2228/index.html">issue-2228</a></strong></li><li><strong><a href="./manual/issue-2246/index.html">issue-2246</a></strong></li><li><strong><a href="./manual/issue-7015/index.html">issue-7015</a></strong></li><li><a href="./manual/multi.html">multi<small>.html</small></a></li><li><a href="./manual/multiple-editors.html">multiple-editors<small>.html</small></a></li><li><a href="./manual/no-error.html">no-error<small>.html</small></a></li><li><strong><a href="./manual/no_sab/index.html">no_sab</a></strong></li><li><strong><a href="./manual/piratical/index.html">piratical</a></strong></li><li><a href="./manual/py-editor.html">py-editor<small>.html</small></a></li><li><a href="./manual/py-editor-failure.html">py-editor-failure<small>.html</small></a></li><li><strong><a href="./manual/py-terminals/index.html">py-terminals</a></strong><ul><li><a href="./manual/py-terminals/no-repl.html">no-repl<small>.html</small></a></li><li><a href="./manual/py-terminals/repl.html">repl<small>.html</small></a></li></ul></li><li><a href="./manual/py_modules.html">py_modules<small>.html</small></a></li><li><strong><a href="./manual/service-worker/index.html">service-worker</a></strong></li><li><a href="./manual/split-config.html">split-config<small>.html</small></a></li><li><a href="./manual/submit.html">submit<small>.html</small></a></li><li><a href="./manual/target.html">target<small>.html</small></a></li><li><a href="./manual/test_display_HTML.html">test_display_HTML<small>.html</small></a></li><li><a href="./manual/test_when.html">test_when<small>.html</small></a></li><li><a href="./manual/worker.html">worker<small>.html</small></a></li></ul></li><li><strong><a href="./python/index.html">python</a></strong></li></ul></body>
17+
<body><ul><li> F438 <strong><span>javascript</span></strong><ul><li><a href="./javascript/async-listener.html">async-listener<small>.html</small></a></li><li><a href="./javascript/config-url.html">config-url<small>.html</small></a></li><li><a href="./javascript/config_type.html">config_type<small>.html</small></a></li><li><strong><a href="./javascript/fetch/index.html">fetch</a></strong></li><li><a href="./javascript/ffi.html">ffi<small>.html</small></a></li><li><a href="./javascript/hooks.html">hooks<small>.html</small></a></li><li><strong><a href="./javascript/issue-2093/index.html">issue-2093</a></strong></li><li><a href="./javascript/js-storage.html">js-storage<small>.html</small></a></li><li><a href="./javascript/js_modules.html">js_modules<small>.html</small></a></li><li><strong><a href="./javascript/loader/index.html">loader</a></strong></li><li><a href="./javascript/mpy-error.html">mpy-error<small>.html</small></a></li><li><a href="./javascript/mpy-no-error.html">mpy-no-error<small>.html</small></a></li><li><a href="./javascript/mpy.html">mpy<small>.html</small></a></li><li><a href="./javascript/py-terminal-main.html">py-terminal-main<small>.html</small></a></li><li><a href="./javascript/py-terminal-worker.html">py-terminal-worker<small>.html</small></a></li><li><a href="./javascript/py-terminal.html">py-terminal<small>.html</small></a></li><li><a href="./javascript/py-terminals.html">py-terminals<small>.html</small></a></li><li><strong><a href="./javascript/pyodide-cache/index.html">pyodide-cache</a></strong></li><li><strong><a href="./javascript/pyodide-lockfile/index.html">pyodide-lockfile</a></strong></li><li><a href="./javascript/storage.html">storage<small>.html</small></a></li><li><strong><span>workers</span></strong><ul><li><strong><a href="./javascript/workers/create_named/index.html">create_named</a></strong></li><li><strong><a href="./javascript/workers/mpy/index.html">mpy</a></strong></li><li><strong><a href="./javascript/workers/py/index.html">py</a></strong></li></ul></li></ul></li><li><strong><a href="./manual/index.html">manual</a></strong><ul><li><a href="./manual/all-done.html">all-done<small>.html</small></a></li><li><a href="./manual/async.html">async<small>.html</small></a></li><li><a href="./manual/camera.html">camera<small>.html</small></a></li><li><a href="./manual/click.html">click<small>.html</small></a></li><li><a href="./manual/code-a-part.html">code-a-part<small>.html</small></a></li><li><a href="./manual/combo.html">combo<small>.html</small></a></li><li><a href="./manual/config.html">config<small>.html</small></a></li><li><a href="./manual/create-element.html">create-element<small>.html</small></a></li><li><a href="./manual/dialog.html">dialog<small>.html</small></a></li><li><a href="./manual/display.html">display<small>.html</small></a></li><li><strong><a href="./manual/donkey/index.html">donkey</a></strong></li><li><a href="./manual/emoji.html">emoji<small>.html</small></a></li><li><a href="./manual/error.html">error<small>.html</small></a></li><li><strong><a href="./manual/game/index.html">game</a></strong></li><li><a href="./manual/html-decode.html">html-decode<small>.html</small></a></li><li><a href="./manual/input.html">input<small>.html</small></a></li><li><a href="./manual/interpreter.html">interpreter<small>.html</small></a></li><li><strong><a href="./manual/issue-2228/index.html">issue-2228</a></strong></li><li><strong><a href="./manual/issue-2246/index.html">issue-2246</a></strong></li><li><strong><a href="./manual/issue-7015/index.html">issue-7015</a></strong></li><li><a href="./manual/multi.html">multi<small>.html</small></a></li><li><a href="./manual/multiple-editors.html">multiple-editors<small>.html</small></a></li><li><a href="./manual/no-error.html">no-error<small>.html</small></a></li><li><strong><a href="./manual/no_sab/index.html">no_sab</a></strong></li><li><strong><a href="./manual/piratical/index.html">piratical</a></strong></li><li><a href="./manual/py-editor.html">py-editor<small>.html</small></a></li><li><a href="./manual/py-editor-failure.html">py-editor-failure<small>.html</small></a></li><li><strong><a href="./manual/py-terminals/index.html">py-terminals</a></strong><ul><li><a href="./manual/py-terminals/no-repl.html">no-repl<small>.html</small></a></li><li><a href="./manual/py-terminals/repl.html">repl<small>.html</small></a></li></ul></li><li><a href="./manual/py_modules.html">py_modules<small>.html</small></a></li><li><strong><a href="./manual/service-worker/index.html">service-worker</a></strong></li><li><a href="./manual/split-config.html">split-config<small>.html</small></a></li><li><a href="./manual/submit.html">submit<small>.html</small></a></li><li><a href="./manual/target.html">target<small>.html</small></a></li><li><a href="./manual/test_display_HTML.html">test_display_HTML<small>.html</small></a></li><li><a href="./manual/test_when.html">test_when<small>.html</small></a></li><li><a href="./manual/worker.html">worker<small>.html</small></a></li></ul></li><li><strong><a href="./python/index.html">python</a></strong></li></ul></body>
1818
</html>

core/tests/manual/game/aliens.css

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/* (c) https://github.com/ryanking13/pyodide-pygame-demo/blob/main/examples/aliens.html */
2+
body {
3+
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
4+
margin: 0;
5+
padding: 20px;
6+
background-color: #f4f4f4;
7+
color: #333;
8+
}
9+
.demo {
10+
background-color: #fff;
11+
margin: 20px auto;
12+
max-width: 1000px;
13+
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
14+
border-radius: 8px;
15+
overflow: hidden;
16+
}
17+
.demo-header {
18+
background-color: #007bff;
19+
color: #fff;
20+
padding: 15px 20px;
21+
font-size: 20px;
22+
}
23+
.demo-content {
24+
padding: 20px;
25+
}
26+
27+
#canvas {
28+
margin: 0 auto;
29+
display: block;
30+
}

0 commit comments

Comments
 (0)
0