- The Backdoomsは、DOOM 1993とThe Backroomsに着想を得た、圧縮型・自己展開型・無限生成のHTMLゲームで、QRコードから直接ブラウザで実行される
- ゲーム全体のコードをURLに入れる方式で、スキャン後はインターネット接続なしでプレイできる完全オフライン構成を目指している
- 圧縮フローは、HTMLをZlibで圧縮してBase64でエンコードした後、JavaScriptのHTMLラッパーに入れ、ブラウザ上で
DecompressionStream APIにより展開して実行する方式
- QR生成は
qr.make(fit=True)で可能な最小のQRバージョンを探し、標準上限のバージョン40とエラー訂正レベルLに収まらなければ失敗する
- モバイル対応は
DecompressionStream APIをサポートする最新モバイルブラウザに限定され、READMEにはEdge、Yandex、Operaが例として記載されている
The Backdoomsが行うこと
- The Backdoomsは、QRコードの中にゲーム全体を収め、Webブラウザで実行するHTMLゲーム
- ゲームはDOOM 1993とThe Backroomsに着想を得ており、圧縮された自己展開Webページの形で構成されている
- QRコードをスキャンするとブラウザですぐに実行され、別途ダウンロードやインストールは不要
- READMEではスキャンしてプレイできると案内されている
- GitHub Pagesでは少し圧縮度を下げたバージョンも提供されている
保存容量の限界に挑む圧縮方式
- プロジェクトの目的は、QRコードの保存容量と圧縮の限界に挑み、軽量WebアプリケーションをQRコード内にホストする方法を示すこと
- 圧縮フローは次の順序で構成される
- 入力HTMLを読み込む
- HTMLをZlibで圧縮する
- 圧縮データをBase64でエンコードする
- JavaScriptベースのHTMLラッパーに挿入する
- HTML全体を
data:text/html;base64,...形式のData URIに変換する
- ブラウザでは
DecompressionStream APIを使って圧縮されたコンテンツを動的に展開し、実行する
- READMEの図には、ブラウザ処理段階で
DecompressionStream 'gzip'とFormat Mismatchの段階が含まれている
QRコード生成ロジック
- QRコード生成ツールは、約2.5kbのゲームをQRコードにするためのフローを提供する
- 実行例は次のとおり
python3 QRGEN.py <your-game.html> <output-qrcode.png>
python3 QRGEN.py EVEN-SMALLER-SLAMMER-BACKROOMS.html qrcode.png
- 生成過程では、
qr.make(fit=True)によりコンテンツ長に合う最小のQRバージョンをまず試す
- 必要なバージョンがQRコード標準の上限である40を超える場合、
fit=Falseでバージョン40を強制する
- 最大限のデータを格納するため、エラー訂正レベルは最も低いLを使用する
- バージョン40とレベルLでもデータが大きすぎる場合、QRエンコードは失敗しエラーを返す
実行と互換性
- プレイ自体に必要なのは最新のWebブラウザのみ
- スキャン後はゲーム全体のコードがURLに入っているため、インターネット接続なしでプレイできる
- モバイルでは
DecompressionStream APIをサポートする最新ブラウザが必要
- READMEにはEdge、Yandex、Operaが例として記載されている
- より小さなQRコード向けのBigIntベースの代替実装はThe BigInt Branchにあるが、モバイルブラウザ互換性は限定的
生成環境とライセンス
- QRコードを自分で生成するには、次の依存関係が必要
-
Python 3.7+
qrcodeライブラリ
- QRコード画像処理用の
pillow
- 依存関係のインストールコマンドは次のとおり
pip install qrcode[pil]
- 開発過程は[MindDump](https://kuberwastaken.github.io/blog/Projects/How-I-Managed-To-Get-Doom-In-A-QR-Code)にまとめられている
- プロジェクトは**MIT License**で公開されており、自由に使用、変更、共有できる
1件のコメント
Hacker News のコメント
DecompressionStream を初めて知り、HTML 部分を調整してさらに数バイト削れました
興味があれば見てもらえるように PR も出しておきました
本当にありがとう。今月いちばんの出来事になりました
本当にすばらしいプロジェクトです
data:URL も新しく知りました。data:URI スキームは知っていて使ったこともありましたが、完全な URL として使えるとは知りませんでしたQR コードの中にすべて収まる似たようなものを作ろうかと考えていましたが、HTTP(s) リンクが必要だと勘違いして先延ばしにしていました。この動画から大きな刺激を受けました: Can you fit a whole game into a QR code?(https://www.youtube.com/watch?v=ExwqNreocpg)
ただ、より広い互換性のためにブラウザベースという逆方向に進み、リポジトリにも出典を記載しておきました
技術初心者なので間抜けな質問かもしれませんが、QR は単にデータをエンコードしたものではないのですか?
QR が保持できる最大データが約 3KB なら平文文字で約 3000 文字に相当するはずですが、ここでの成果はこの Doom 風ゲームがその程度のサイズの実行可能なコードとして動く、ということなのか気になります
QR 標準における 8ビットエンコードの意味と目的は少し曖昧に見えますが、基本的な解釈は JIS8 および Shift JIS 文字セットで、他の ECI では 8ビットのバイト値を直接表します
いずれにせよ QR コードに任意のバイナリデータを保存することは可能で、
qrencodeツールはこれを標準でサポートしていますただしデコーダーは QR にテキストが入っていると仮定することが多く、対応は厄介です。zbar がデータを
iconvに通して壊してしまう問題があったため、バイナリ QR デコード用のパッチを送ったこともありますもともとは4096ビット RSA 秘密鍵を QR コードとして出力したかっただけなのですが、その後、人々がビデオゲームまで QR にエンコードし始めて、本当にすばらしいです
https://youtu.be/ExwqNreocpg
https://news.ycombinator.com/item?id=24287347
iPhone 標準の QR コードスキャナーでスキャンしたら、「利用可能なデータが見つかりません」と表示されました
data:URI URL をサポートしていないためですたとえば自己完結型のウェブページ
Hi!はdata:text/html;base64,PGh0bWw+PGJvZHk+SGkhPC9ib2R5PjwvaHRtbD4=としてエンコードでき、ブラウザに貼り付けるとHi!がレンダリングされますしかし、これを QR コードにすると、その状況では動作しません
ほとんどのスマートフォンは大きな QR コードをうまく読み取れないので、https://qrscanner.org/ のようなものが必要です
それにスマートフォンでは動作しないはずで、サイズ制限のため、その互換性まで入れることはできませんでした
URL 入力の時間を省くために、あちこちに貼られた QR コードをよくスキャンしますが、QR コードをスキャンするだけで任意コード実行が可能だと考えると、かなり怖いです
キャンバスの CSS に
image-rendering: pixelatedを入れると、ぼやけずにくっきりしたピクセル感で見えそうです次のプロジェクトは QR コードになった LLM だといいですね
関連: https://www.reddit.com/r/OpenAI/comments/138kbhs/someone_sho...
LLM ではありませんが、それでもかなりクールなチャットボットです
https://github.com/Kuberwastaken/MiniLMs/tree/main/SYNEVA
ゲームトレーラーのリンクが「Fly me to the moon - 19 September 2024」というショート動画につながっています
ミスのようです
こういう超小型ゲームプロジェクトが本当に好きです
.kkrieger を思い出します
https://en.wikipedia.org/wiki/.kkrieger
これからもかっこいいものを作り続けてほしいです、kuberwastaken
友人と、多少関連するアイデアについて話したことがあります
3D プリント用の STL ファイルを QR コードに丸ごとエンコードして実物に貼れば、作った物をスキャンするだけで再出力できるのではないかと思いました
調べてみるとデータ量が多すぎるようで、多色 QR コードまで調べましたが、単により大きな QR コードを作れるとは知りませんでした
テーブルは板材の切断だけで済むので 2D ファイルをエンコードしたのですが、それでも概念実証のためにカスタム圧縮アルゴリズムまで使う必要がありました
https://johnkestner.com/rev/