【Python】pygameをjavascriptで動かす
最近はスマホで pythonの開発が行えるということで、スキマ時間にコツコツとゲーム開発できる環境としてpython + pygameを検討しています。
デスクトップアプリなどは普通に作れますが、せっかく作るのであればブラウザ上でも動かしたいという欲求がでてきたので pythonコードを javascript に変換する方法を探してみました。
調べたところ、残念ながら日本語の情報を見つけることができなかったので英語の記事を探って試してみたことを記録しておきます。
Pyjsdl
pygameのAPI設計を踏襲したjavascriptのライブラリを作ってくださっている方がいました。
ちなみに Java 版のPyJ2Dというライブラリもあるようです。
なお、本家の方が新しいバージョンが公開されています。以下のリンクかgithubのソースをダウンロードします。※pipでは配布されていない様です。

本家の説明によるとPyjs というPythonコードをJavascriptコードに変換するコンパイラを使用して変換するとのことでした。
ダウンロードしたpyjsdlのソースコードをみると、pygame APIのインターフェイスに習ってAPIが定義されています。その中身は、Pyjs の HTML5 Canvasの機能で描画するコードが書かれていました。
なるほど、それならブラウザで動くわけですね。
もし、WebGLに対応した javascriptコンパイラーがあれば同じような形でPyjsdl に代わるGlueコードを自作すれば描画の高速化が狙えるかもしれないですね。(本格的にブラウザゲーム作りたくなったらやってみるかも)
Pyjsdlのサンプルソースをダウンロード
動作検証の為、本家のサンプルソースをダウンロードしてみました。リンク場所がわかりにくいですがこちらです。
サンプルソース https://s3.gatc.ca/files/Pyjsdl_App.zip

zipを任意の場所に解凍すると、serpentduel.py というソースがあります。
サンプルソースの中でポイントになるのは、pyjsdl を pygameの名前でインポートする部分です。
import pyjsdl as pygame #pyjsdl import
APIの定義(インターフェイス)が同じなので、この最小の変更で javascript へ変換する準備ができたことになります。
Pyjsdlのインストール
インストールと言っても zipファイルを展開し、フォルダ名を pyjsdl にしてサンプルソースのプロジェクトに突っ込みます。
※私が最近 pythonを勉強しはじめたばかりなので pip install に相当するインストール方法があるのかもしれないです。
ただ、pip は使えず、setup.py も含まれていないので次節で Pyjsにコンパイルさせる為に直接プロジェクトフォルダに入れる方法をとりました。
Pyjsのインストール
似た様な名前が続きますが(笑)、これが Python => javascript に変換するコンパイラです。
pipのコマンドでインストールできます。
pip install git+https://github.com/pyjs/pyjs.git#egg=pyjs
これで pyjsbuildコマンドが使えるようになるので サンプルの serpentduel.pyを指定して、js にコンパイルします。
pyjsbuild <対象ソース>.py
するとカレントディレクトリにoutputというディレクトリが作成されて、そこに依存関係のあるソースと共に js に変換された web ページ一式が出力されますので、動作確認用に適当なサーバーにアップします。
※ローカルマシン上で実行しようとすると[Uncaught DOMException: Blocked a frame with origin “null” from accessing a cross-origin frame.]というエラーが吐かれて動きません。
これはセキュリティ的に危険なクロスサイトスクリプティングを防止する為のエラーで、ブラウザ起動時などに引数を与えることで開発時のみ一時的に許可できる様です。気になる方は調べてみてください。
個人的には実際の動作を確認する意味でも検証用のスペースは用意しておいた方が良いと思います。
メモ:Pyjsdlのリソース一覧
https://gatc.ca/projects/pyjsdl/resources/
上記を私が試した試した結果
サンプルプロジェクトを自分でコンパイルしてアップロードしたものです。
http://nora-soft.sakura.ne.jp/sample/js/output/serpentduel.html
まとめ
クロスプラットフォーム開発のできる環境として、UnityもWebGLに対応しているのですが、最近の生活の中で mac book 片手に開発する余裕がないので、スマホでもコツコツアプリを作れる環境として python を調べ始めたのが今回の記事を書くきっかけでした。
個人的には javascript にはどうも慣れないし、できれば同じソースを元に作りたかったということで、python => javascript に変換できる環境は魅力的でした。
需要は高い気がするのですが、これらの技術については、まだ発展途上の印象も受けています。より手軽に低コストで開発できる様に技術が発展していくことを願っています!
ディスカッション
コメント一覧
はじめまして、ドンナシーと申します。
プログラミングの初心者(mac使用)です。
初めてpygameでゲームを作ったのでWordpressで公開しようとしたところ、pygameはブラウザ表示できないと知り途方に暮れておりました。
そこでこちらの「【Python】pygameをjavascriptで動かす」に辿り着きpyjsdlをダウンロードしたのですが、readme.txtを翻訳しても理解できず行き詰まってしまいました。
いくつか教えていただけませんでしょうか。
質問1:見出し「Pyjsdlのインストール」内の【フォルダ名を pyjsdl にしてサンプルソースのプロジェクトに突っ込む】という部分の【フォルダ名を pyjsdl にして】とはserpentduel→pyjsdlでしょうか? また【サンプルソースのプロジェクトに突っ込む】についてもう少し詳しく解説をお願いいたします。
質問2:見出し「Pyjsのインストール」内の【pipのコマンドでインストール】とはmacのターミナルで実行すれば良いでしょうか?
それ以下の部分も現時点では理解できませんが「Pyjsのインストール」が出来れば自力で進められるかもしれませんので、以上の質問にお答えいただければ幸いです。
よろしくお願いいたします。
ドンナシーさん。こんにちは。
この記事はずいぶん前に書いたもので内容が整理されておらず、わかりにくくてすみません。
いただいた質問ですが、
———————-
質問1:Pyjsdlのインストール
———————-
Pyjsdl のライブラリをダウンロードするとバージョン番号などが付与されたzipファイルがダウンロードされます。(例:pyjsdl-0.25.1.zip)
これを解凍してフォルダ名を pyjsdl に変えてください。pyjsdl-0.25.1→pyjsdl
そして pyjsdl フォルダを pygame向けに作成した.pyファイルがある階層に移動してください。
※この記事の場合は「Pyjsdlのサンプルソース」でご紹介した Pyjsdl_App.zip を解凍して、このフォルダの直下におきます。
readme.txt ではこのことが書かれています。
———————-
質問2:Pyjsのインストール
———————-
はい。mac のターミナルで pipコマンドを実行すればインストールされます。
pipコマンドが使えない場合は、他の記事を参考にしてただければと思います。
【Python】macOSでpipを使えるようにする
https://qiita.com/ohbashunsuke/items/e7c673db606a6dced8a6
————–
その後のことですが、pyjsbuild で出力された html ファイルを開発PC(ローカル)上で開くと javascript の開発で起こりがちなクロスサイトスクリプティングのエラーに遭遇する場合があります。
それについても調べていただければと思いますが、ブラウザのセキュリティを一時的に変更する事でエラーが回避できます。
ですが、サーバー上で動かす場合(公開するためのサーバー環境)では問題ないと思います。
norakkoさん、こんばんは。
お返事遅くなり申し訳ありません。
わざわざ質問に回答していただきありがとうございます。
実践はこれからしてみますが、まずはお礼のコメントをさせていただきます。
本当にありがとうございました。
また、不明点あれば質問させていただくかもしれませんが、よろしくお願いいたします。
norakkoさん、こんばんは。
Pyjsのインストール完了しました。
その後のjs にコンパイルする作業(のちほど質問させていただきます)でエラーが頻発し、ネットで検索しながら進めていく中で疑問が湧いてきました。
それは、私がpython3.9を使用していることが原因なのではないか?ということです。
いろいろ調べている中で「Pyjsはpython3に対応していない」という記事も目にしました。
質問1:
pythonのバージョンは2を使うべきでしょうか?
質問2:
見出し「Pyjsのインストール」内の【サンプルの serpentduel.pyを指定して、js にコンパイルします。
pyjsbuild .py】
の「サンプルの serpentduel.pyを指定」するとはどういうことでしょうか?
「pyjsbuild .py」は pyjsbuild をターミナルで実行すると理解しています。
たびたびの質問でおそれいりますが、よろしくお願いいたします。
norakkoさん
さきほどの質問2の
【「pyjsbuild .py」は pyjsbuild をターミナルで実行すると理解しています。】
は、【pyjsbuild をターミナルで実行する】の間違いでした。
すみません。
norakkoさん
送信するとコメントの一部が消えてしまうようなので、もう一度送信いたします。
【pyjsbuild 自作ゲームのpyファイル をターミナルで実行する】
でした。
よろしくお願いいたします。
ドンナシーさん。
すみません。
当時の作業環境が手元に無いので動作確認できておりませんが、
いまわかる範囲で回答いたします。
————-
>質問1:
>pythonのバージョンは2を使うべきでしょうか?
————-
恐らくそうだと思います。当時の記憶があいまいですが、私は Python 2.7 を使用していたと思います。
Pyjsの公式情報を読んでもサポートしているPythonバージョンについて明記されていなかったのですが、Pyjsデスクトップ版の説明ではJSONライブラリの関係でPython2.6以降を勧める一文がありました。
https://github.com/pyjs/pyjs#:~:text=All%20ports%20of%20Pyjs%2DDesktop%20require%20a%20JSON%20library%3B%20simplejson%20is%20recommended%20if%20the%20version%20of%20python%20is%202.5%20or%20older.%20Python%202.6%20and%20above%20come%20with%20a%20json%20library%20installed%20by%20default.
————-
>質問2:
>見出し「Pyjsのインストール」内の【サンプルの serpentduel.pyを指定して、js にコンパイルします。
>pyjsbuild .py】の「サンプルの serpentduel.pyを指定」するとはどういうことでしょうか?
>「pyjsbuild .py」は pyjsbuild をターミナルで実行すると理解しています。
————-
ご認識の通り pyjsbuild はターミナルで実行するコマンド名です。
pyjsbuild コマンドの引数として、自作ゲームのpyファイルを指定するという認識であっております。
ただ、恐らく質問1のpythonバージョンの問題があると思いますので、
まずはpyjsのドキュメント(GithubのWiki)などを参考に環境構築できたかテストしていただくのが良いと思います。
Getting Started
https://github.com/pyjs/pyjs/wiki/GettingStarted
よろしくお願い致します。
norakkoさん
早速の回答ありがとうございます。
参考リンクまで付けてくださり感謝です。
pythonのバージョン問題から確認してみます。
ありがとうございました。
norakkoさん
お世話になります。
前回、お返事を頂いてからPCの初期化、OS再インストールを数回するなど時間が経ってしまいました。
その後、python2.7の作業環境を作り、PC上でゲームが動くことも確認し、jsへコンパイルする作業も無事に終わりサーバーへアップするところまで来ましたが、アップするファイルの組み合わせを変えてもブラウザに表示されず苦戦しています。
XserverにアップしてWordPressのHPにゲームを載せたいので
下記のサイトを参考にしていますが、アップするファイルまでは分かりませんでした。
https://enjoy-days.net/game-wordpress
現在、手元には元々の
・pngファイル
・wavファイル
・pyファイル
に加えて
・pyjsdlディレクトリと
・outputディレクトリがあります。
outputディレクトリには
・7種類のhtmlファイル(シンプルなhtmlファイル以外にブラウザ.cacheのような6種類)
・3種類のjsファイル
・libディレクトリ(中に5種類のjsファイル)があります。
質問1:
このなかでアップロードに必要なファイルはどれでしょうか?
それらをひとつのディレクトリにまとめるべきか、個別にアップするべきか、どちらでもかまわないでしょうか?
質問2:
アップ後にブラウザで表示確認をする際(WordPressに埋め込む前)のURLは、outputディレクトリのシンプルなhtmlで合っているでしょうか?
例えばXserverのpublic_html直下にoutputディレクトリのみをアップし、ブラウザでシンプルなhtmlを打ち込むと ImportError: No module named pygame, pygame in context None
とエラーが出るので
元々のpyファイルをpublic_html直下やoutputディレクトリ内に置いても同じエラーが出ます。
お時間のある時で構いませんので、よろしくお願いいたします。
ドンナシーさん
回答が遅くなりすみません。
—————
質問1:
—————
「上記を私が試した試した結果」の項に記載しているサンプルでは output フォルダの中身をそのままアップロードしています。
※outputフォルダ自体は名前は変更しても大丈夫でした。
ただおそらく、outputフォルダ内は変更せずにそのままアップロードするのが良いのではないかと思います。
—————
質問2:
—————
outputフォルダ内には複数のhtmlファイルが含まれていますがメインとなるhtml (pyファイル名.html)を開けばゲームが動くのではないかと思います。
たとえば以下の通りです。
http://nora-soft.sakura.ne.jp/sample/js/output/serpentduel.html
ですがドンナシーさんの環境ではpygameが読み込めないということになっているようですね。
サンプルソースの serpentduel.py では、
import pyjsdl as pygame #pyjsdl import
と記述して pyjsdl を pygame という名前で扱えるようにしています。
ドンナシーさんが制作されているゲームでも、この記述を追加してからjsにコンパイルしてみていただくと解決するかもしれません。
※通常通りpythonで開発する際はこの記述を消す必要があるので、ここがいささか面倒なところですが…。
これで解決に向かうとよいのですが、よろしくお願いいたします。
norakkoさん
早速のお返事ありがとうございます。
import pyjsdl as pygame
が抜けていたので記述したところ、前回のエラーの代わりに
TypeError: Illegal constructor
が出てしまいました。
原因を検索しても解決できませんでしたが、これ以上はnorakkoさんにお聞きする訳にもいきませんので、Unityで作り直そうと思います。
ゲーム自体はとてもシンプルなのでUnityでもなんとか作れるだろうと思っています。
度々の質問にも丁寧に教えてくださり、本当にありがとうございました。
norakkoさんのように知見を公開していただくことは、私のような初心者にはとても貴重な情報となります。
norakkoさんのおかげで色々と学ぶことができました。
改めて感謝いたします。
少し早いですが、良いお年をお迎えください。
ドンナシーさん
お返事ありがとうございます。
承知しました。
ドンナシーさんならunityでもきっと作れる様になると思います。
応援しています。
こちらこそ、この記事が誰かの役に立つ日が来るとは想像していなかったので良い機会をいただけたと思います。
また、今回返信させていただく上でこの記事を読み直すとだいぶ荒削りでわかりにくかっただろうなと思いました。
そういった反省の機会にもなりました。
ご質問いただきありがとうございました。