0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

「Pygameラッパーライブラリ開発記録|NW.js断念からGo自鯖突破まで──デスクトップ出力トラブルシューティング全史」

Posted at

デスクトップ出力での大冒険

PygameをクロスプラットフォームでWebアプリもデスクトップアプリも
Python環境なしでも実行できるものを出力したい、ってことで試行錯誤してました。
NW.jsでの挑戦から、Windows用Webサーバー「MiniWeb」での一瞬の成功、
そしてGoサーバーでの突破まで──その全記録をまとめます。

この記事は、同じように pygame × WASM(WebAssembly) × デスクトップ配布 に挑戦する人の参考になれば幸いです。


忙しい人のために:この記事のまとめ

  • NW.jsは技術的に動かず断念。
  • Windows用Webサーバー「MiniWeb」で一度は成功するも、Windows専用で配布に不向き。
  • Goのhttp.FileServerでクロスプラットフォームを狙うが、MIME問題で失敗。
  • MIME補正(.wasm=application/wasm, .apk=application/zip)+CDNリダイレクトで突破。
  • 最小構成(index.html + myapp.apk + favicon.png)で動作確認に成功。
  • 結論:Goサーバー同梱方式がPygameラッパーライブラリのデスクトップ配布解決策。

トラブルシューティング時系列

1. NW.jsでの挑戦

  • 当初はNW.jsでラップして配布を狙った。
  • しかしNode.jsベースの仕組みと、pygbagが生成する WASMローダー が干渉してしまい、まともに動作せず。
  • 具体的には、NW.jsの内部環境がブラウザAPIを完全に再現していないため、fetch() での .apk 読み込みや SharedArrayBuffer の扱いでエラーが発生。
  • 「これは時間をかけても厳しい」と判断して断念。

2. 自鯖アプローチに転換

  • 「ローカルにサーバーを立てて配信すればいいのでは?」と発想を転換。
  • 軽量サーバーとして MiniWeb を試す。

3. MiniWebでの成功と限界

  • index.htmlmyapp.apk を配信したら、なんと動いた!
  • しかしMiniWebはWindowsバイナリ前提で、クロスプラットフォーム性に欠ける。
  • 「動くけど、配布用には現実的じゃない」と課題が残る。
  • 更新が2013年でストップしてて古いし。

4. Goサーバーに挑戦

  • 「Goなら単一バイナリでクロス配布できる」と判断。
  • http.FileServer を使って自鯖を実装。
  • しかしブラウザは真っ白、コンソールには archives 404MEDIA USER ACTION REQUIRED
  • クリックしても myapp.apk がロードされない。

5. 原因の特定

  • GoのFileServerが .wasm.apkapplication/octet-stream で返していた。
  • pygbagローダーは .wasm=application/wasm.apk=application/zip を期待している。
  • MIMEが違うため、apkマウントが始まらなかった。

6. 修正と突破

  • GoサーバーにMIME補正を追加:
    • .wasm → application/wasm
    • .apk → application/zip
  • さらに /archives/ をCDNにリダイレクトする処理を追加。
  • → ついにGoサーバーでも動作!しかもMiniWebより高速。

MIME補正についての実際のコード断片はこんな感じ:

import (
    "mime"
    "net/http"
)

func main() {
    // MIME補正
    mime.AddExtensionType(".wasm", "application/wasm")
    mime.AddExtensionType(".apk", "application/zip")

    // ./web フォルダをルートとして配信
    fs := http.FileServer(http.Dir("./web"))
    http.Handle("/", fs)

    http.ListenAndServe(":8000", nil)
}

/archives/ のCDNリダイレクト処理

http.HandleFunc("/archives/", func(w http.ResponseWriter, r *http.Request) {
    target := "https://cdn.example.com" + r.URL.Path
    http.Redirect(w, r, target, http.StatusFound)
})
  • /archives/ 以下のリクエストはすべて外部CDNに転送される。
  • ローカルには最小構成(index.html + myapp.apk + favicon.png)だけ置いておけばOK。

7. 最小構成での動作確認

  • index.html + myapp.apk + favicon.png の3ファイルだけで動作することを確認。
  • 「CDN参照モードなら最小構成で配布可能」という結論に到達。

結論

  • NW.jsは使えなかった。
  • MiniWebは動いたが配布に不向き。
  • Goサーバー同梱方式こそが現実解。

Pygameラッパーライブラリの「デスクトップ配布モード」は、Goサーバーを同梱してブラウザを自動起動させる方式に落ち着きました。
結果的に「軽量でクロスプラットフォーム」「Python環境不要」「最小構成で配布可能」という理想的な形に。


参考リンク


最後までお読みいただきありがとうございました!
この記事が役に立ったら『いいね』や『ストック』で応援していただけると嬉しいです。
Pygameラッパーライブラリの開発記録は今後も追加予定です 🚀

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?