見出し画像

ブラウザ版Pyxelでファイルアップロード

レトロゲームエンジンPyxelで、jsモジュールを使えばファイルのダウンロードができる、という記事を以前に投稿しました。

ダウンロードができるならアップロードもできるはず!ということで試してみました。
地味に苦戦したのですが、結論としては問題なくできます。

以下、動作イメージです。Lorem ipsumのサンプルテキストを読み込ませて画面に表示しているだけです。

ソースはこちら。
わかりやすくするため、HTML内に直接Pyxelのコードを書き込んでいます。

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Pyxel x JavaScript Sample</title>
    <script src="https://cdn.jsdelivr.net/gh/kitao/pyxel/wasm/pyxel.js"></script>
  </head>
  <body>
    <pyxel-run
      script="
        import pyxel
        from js import document, FileReader
        from pyodide.ffi import create_proxy

        class App:
            def __init__(self):
                self.texts = None
                pyxel.init(160, 120)
                document.body.addEventListener('dragover', create_proxy(self.on_dragover))
                document.body.addEventListener('drop', create_proxy(self.on_drop))
                pyxel.run(self.update, self.draw)
    
            def update(self):
                pass

            def draw(self):
                pyxel.cls(0)
                if self.texts:
                    x = 0
                    y = 0
                    for text in self.texts:
                        pyxel.text(x * 4, y * 8 + 1, text, 7)
                        x += 1
                        if text == '\n':
                            y += 1
                            x = 0
                else:
                    pyxel.text(50, 57, 'Drop file here.', 7)
            
            def on_dragover(self, e):
                e.preventDefault()

            def on_drop(self, e):
                e.preventDefault()
                files = e.dataTransfer.files
                for file in files:
                    reader = FileReader.new()
                    def on_load(e):
                        self.texts = reader.result
                    reader.onload = on_load
                    reader.readAsText(file)
                    break

        App()
      "
    ></pyxel-run>
  </body>
</html>

あまりまともに解説できませんが、以下あたりがポイントでしょうか。

  • ファイルの中身を読み込むためには、FileReaderオブジェクトをjsモジュールからインポートしてFIleReaderオブジェクトから操作する必要がある

  • addEventListenerする際にはハンドラ関数を直接登録するのではなく、pyodideからcreate_proxyをインポートしてcreate_proxyの引数としてハンドラ関数を登録する必要がある(でないとイベントが破棄されてしまう)

いやPyxelって小規模なレトロゲーム作るゲームエンジンだろ、アップロードさせる必要ある?というツッコミはごもっともなのですが、Pyxel製のツールを作りたい際なんかには役に立つかもしれません。

Pyxel本体もバージョン2.0の開発が進んでいるようで(2023/10/9現在)楽しみですね。

この記事が気に入ったらサポートをしてみませんか?