PyxelプログラムからJavaScriptを実行する
本記事は,高校生向けのプログラミング学習からは離れた内容になります。Pyxelで作成したゲームをPyxel Webの機能を利用して公開している人を読者に想定した記事です。
Pyxel Web が Pyodide の仕組みを利用している(2023年3月現在)ので,下記サイトを参考に,PyxelのプログラムからJavaScriptを使ってHTMLのDIV要素のテキストを変更する処理を試してみました。(成功したのでローカルストレージにデータを保存する実験もしました)
参考サイト Type translations — Version 0.22.1
Calling JavaScript functions from Python
PyxelプログラムからWeb画面にメッセージを表示する
HTMLファイル例
DOMを操作したいので,HTMLファイルを作成して,.pyファイルを指定して実行する形式の例を示します。(pyxel app2html で変換したHTMLファイルでもJavaScriptのalert() 呼び出しができました)
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Calling JavaScript functions from pyxel</title> <style> #msg{ position: absolute; top: 5px; left: 5px; border: solid 1px #eeeeee; width: 10rem; color: #aaa; background: black } </style> </head> <body> <script src="https://cdn.jsdelivr.net/gh/kitao/pyxel/wasm/pyxel.js"></script> <pyxel-run root="." name="jstest.py"></pyxel-run> <div id="msg">This is a html.</div> </body> </html>
・ID msg のdivタグが書き換えたい要素です。
div要素そのままだと画面上で見えなかったので,スタイルを指定しました。
Pyxelのプログラム例(マウス座標)
マウスポインタの座標をdiv要素に表示します。
jstest.py
from js import document import pyxel pyxel.init(80,64) pyxel.mouse(True) x=y=0 def update(): global x,y x = pyxel.mouse_x y = pyxel.mouse_y if pyxel.frame_count % 3 == 0: document.getElementById("msg").innerText = "(x,y)=("+str(x)+","+str(y)+")" return def draw(): pyxel.cls(1) pyxel.text(1,1, "x="+str(x),7) pyxel.text(1,8, "y="+str(y),7) return pyxel.run(update,draw)
Webサーバーに配置して実行
ブラウザでのデモ
http://benkyoubox.starfree.jp/100_game/10_pyxel/JStest/callsample.html
Pyxelのプログラム例(乱数表示)
div要素の書き換えが動き続けると,表示内容をクリップボードにコピーできなかったので,1回の出力に変えてみました。
rnditest.py
from js import document import pyxel pyxel.init(80,64) val = 0 def update(): global val if pyxel.btnp(pyxel.KEY_SPACE): val = pyxel.rndi(1,100) document.getElementById("msg").innerText = "val = "+str(val) return def draw(): pyxel.cls(1) pyxel.text(1,1, "Press space",7) pyxel.text(1,8, "val = "+str(val),7) return pyxel.run(update,draw)
HTMLファイル側の指定.pyファイル名を変更して実行してみます。
ブラウザでのデモ(スペースキーを押すと,乱数を表示します)
http://benkyoubox.starfree.jp/100_game/10_pyxel/JStest/copytest.html
※Ctrl+Cのショートカットキーは,どこかで止めているようで働きませんでした。
Edgeの右クリックメニューからコピーが選択出来て,Web画面に表示した val = 73 をクリップボードにコピーすることができました。
ローカルストレージにデータを保存する
JavaScriptが実行できたので,ローカルストレージにデータを保存して読み出してみます。(ローカルストレージはWebブラウザにテキストデータを保存できる仕組みです。セキュアではないので重要な情報は扱わないこと)
HTMLファイル例
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Calling JavaScript functions from pyxel</title> </head> <body> <script src="https://cdn.jsdelivr.net/gh/kitao/pyxel/wasm/pyxel.js"></script> <pyxel-run root="." name="lstest.py"></pyxel-run> </body> </html>
Pyxelのプログラム例(データ保存と読み込み)
lstest.py
from js import localStorage import pyxel pyxel.init(240,160) val = "no data" def update(): global val if pyxel.btnp(pyxel.KEY_S): localStorage.setItem("_savetest_pyxel", "I am pyxel. "+str(pyxel.frame_count)); if pyxel.btnp(pyxel.KEY_L): val = localStorage.getItem("_savetest_pyxel") return def draw(): pyxel.cls(1) pyxel.text(1,1, "Press [S]ave or [L]oad",7) pyxel.text(1,8, "val = "+str(val),7) return pyxel.run(update,draw)
・Sキーを押すと,ローカルストレージにキー"_savetest_pyxel"でデータを保存します。
・Lキーを押すと,ローカルストレージから読み込んだデータを表示します。
ブラウザでのデモ
http://benkyoubox.starfree.jp/100_game/10_pyxel/JStest/lstest.html
SaveしてLoadして表示を確認→ブラウザを終了してもう一度アクセス→Loadして表示できれば成功
※プライベートブラウズの場合は動作できません
実際にアプリに組み込むにはエラーを考慮する(※)必要があると思いますが,ゲームデータの保存に利用できるかもしれませんので,参考にしてください。
(※JavaScript側にtry catchを入れた関数を定義して呼び出すなど)
次の記事(自作の関数呼び出し例)
kinutani.hateblo.jp