1 điểm bởi GN⁺ 2025-04-19 | 1 bình luận | Chia sẻ qua WhatsApp
  • The Backdooms là một game HTML dạng nén, tự giải nén và sinh màn chơi vô hạn, lấy cảm hứng từ DOOM 1993 và The Backrooms, chạy trực tiếp trong trình duyệt từ mã QR
  • Toàn bộ mã của game được đưa vào URL; sau khi quét, mục tiêu là có cấu trúc hoàn toàn ngoại tuyến, cho phép chơi mà không cần kết nối Internet
  • Luồng nén gồm nén HTML bằng Zlib, mã hóa Base64, đưa vào một wrapper HTML JavaScript, rồi trong trình duyệt giải nén và chạy bằng API DecompressionStream
  • Việc tạo QR dùng qr.make(fit=True) để tìm phiên bản QR nhỏ nhất có thể; nếu không nằm trong giới hạn chuẩn là version 40 và mức sửa lỗi L thì sẽ thất bại
  • Hỗ trợ di động chỉ giới hạn ở các trình duyệt di động hiện đại hỗ trợ API DecompressionStream; README nêu Edge, Yandex, Opera làm ví dụ

The Backdooms làm gì

  • The Backdooms là một game HTML chứa toàn bộ game trong mã QR và chạy trong trình duyệt web
  • Game lấy cảm hứng từ DOOM 1993The Backrooms, được cấu thành dưới dạng trang web nén tự giải nén
  • Khi quét mã QR, game chạy trực tiếp trong trình duyệt, không cần tải xuống hay cài đặt riêng
  • README cho biết có thể quét để chơi
  • GitHub Pages cũng cung cấp phiên bản nén ít hơn một chút

Cách nén đẩy giới hạn dung lượng lưu trữ

  • Mục tiêu của dự án là đẩy giới hạn dung lượng lưu trữ của mã QR và nén, đồng thời cho thấy cách host một ứng dụng web nhẹ bên trong mã QR
  • Luồng nén gồm các bước sau
    • Đọc HTML đầu vào
    • Nén HTML bằng Zlib
    • Mã hóa dữ liệu đã nén bằng Base64
    • Chèn vào wrapper HTML dựa trên JavaScript
    • Chuyển toàn bộ HTML thành Data URI dạng data:text/html;base64,...
  • Trong trình duyệt, API DecompressionStream được dùng để giải nén động nội dung đã nén và chạy nó
  • Sơ đồ trong README có bao gồm DecompressionStream 'gzip' và bước Format Mismatch ở giai đoạn xử lý của trình duyệt

Logic tạo mã QR

  • Công cụ tạo mã QR cung cấp luồng để biến game khoảng 2.5kb thành mã QR
  • Ví dụ chạy như sau
python3 QRGEN.py <your-game.html> <output-qrcode.png>
python3 QRGEN.py EVEN-SMALLER-SLAMMER-BACKROOMS.html qrcode.png
  • Quá trình tạo trước tiên thử phiên bản QR nhỏ nhất phù hợp với độ dài nội dung bằng qr.make(fit=True)
  • Nếu phiên bản cần thiết vượt quá giới hạn chuẩn của mã QR là 40, công cụ sẽ ép dùng version 40 với fit=False
  • Để chứa được nhiều dữ liệu nhất, mức sửa lỗi thấp nhất là L được sử dụng
  • Nếu dữ liệu vẫn quá lớn ngay cả với version 40 và mức L, quá trình mã hóa QR sẽ thất bại và trả về lỗi

Chạy và khả năng tương thích

  • Việc chơi game chỉ cần một trình duyệt web hiện đại
  • Sau khi quét, toàn bộ mã của game nằm trong URL nên có thể chơi mà không cần kết nối Internet
  • Trên di động, cần trình duyệt hiện đại hỗ trợ API DecompressionStream
    • README nêu Edge, Yandex, Opera làm ví dụ
  • Một triển khai thay thế dựa trên BigInt cho mã QR nhỏ hơn có trong The BigInt Branch, nhưng khả năng tương thích với trình duyệt di động bị hạn chế

Môi trường tạo và giấy phép

  • Để tự tạo mã QR, cần các phụ thuộc sau
    • Python 3.7+

      • Thư viện qrcode
      • pillow để xử lý ảnh mã QR
      • Lệnh cài đặt phụ thuộc như sau
pip install qrcode[pil]
- Quá trình phát triển được tổng hợp trong [MindDump](https://kuberwastaken.github.io/blog/Projects/How-I-Managed-To-Get-Doom-In-A-QR-Code)
- Dự án được phát hành theo **MIT License**, có thể tự do sử dụng, chỉnh sửa và chia sẻ

1 bình luận

 
GN⁺ 2025-04-19
Ý kiến trên Hacker News
  • Lần đầu biết đến DecompressionStream, và đã tinh chỉnh phần HTML để giảm thêm vài byte
    Tôi cũng đã gửi PR, nếu bạn quan tâm thì xem thử

    • Nhờ phần dung lượng có thêm đó, tôi đã có thể thêm hỗ trợ màn hình cảm ứng, di chuyển tốt hơn, sinh kẻ địch và cả xử lý sát thương
      Thật sự cảm ơn, đây là điều tuyệt nhất trong tháng này
  • Dự án thật sự rất tuyệt
    Tôi cũng mới biết về URL data:; trước đây tôi biết và từng dùng scheme URI data:, nhưng không biết nó có thể được dùng như một URL hoàn chỉnh
    Tôi từng nghĩ đến việc làm thứ gì đó tương tự nằm trọn trong mã QR, nhưng đã trì hoãn vì lầm tưởng rằng cần liên kết HTTP(s); video này đã truyền cảm hứng lớn cho tôi: Can you fit a whole game into a QR code?(https://www.youtube.com/watch?v=ExwqNreocpg)

    • Tôi cũng đã xem video đó vào khoảng thời gian phong tỏa và được truyền cảm hứng; nó thật sự rất hay
      Tuy nhiên, để có khả năng tương thích rộng hơn, tôi đã đi theo hướng ngược lại là dựa trên trình duyệt, và cũng đã ghi nguồn trong kho lưu trữ
  • Tôi là người mới về kỹ thuật nên có thể đây là câu hỏi ngốc, nhưng QR chẳng phải chỉ là dữ liệu được mã hóa sao?
    Nếu lượng dữ liệu tối đa mà QR chứa được khoảng 3KB, tương đương khoảng 3000 ký tự văn bản thuần, thì tôi muốn biết thành tựu ở đây có phải là trò chơi giống Doom này chạy được dưới dạng mã thực thi có kích thước cỡ đó không

    • Mã QR có nhiều chế độ mã hóa như số, chữ-số, 8-bit, Hán tự, v.v.; phổ biến nhất là mã hóa chữ-số, còn đặc nhất là mã hóa 8-bit lưu trực tiếp dữ liệu nhị phân
      Trong chuẩn QR, ý nghĩa và mục đích của mã hóa 8-bit có vẻ hơi mơ hồ, nhưng cách diễn giải mặc định là bộ ký tự JIS8 và Shift JIS; trong các ECI khác thì nó biểu diễn trực tiếp giá trị byte 8-bit
      Dù sao thì việc lưu dữ liệu nhị phân tùy ý trong mã QR là có thể, và công cụ qrencode hỗ trợ mặc định việc này
      Tuy nhiên, việc hỗ trợ khá rắc rối vì các bộ giải mã thường giả định QR chứa văn bản; tôi từng gửi bản vá giải mã QR nhị phân do zbar làm hỏng dữ liệu khi đưa qua iconv
      Ban đầu tôi chỉ muốn in khóa bí mật RSA 4096 bit dưới dạng mã QR, nhưng sau đó mọi người bắt đầu mã hóa cả trò chơi điện tử vào QR, thật sự rất tuyệt
      https://youtu.be/ExwqNreocpg
      https://news.ycombinator.com/item?id=24287347
  • Tôi quét bằng trình quét mã QR mặc định của iPhone thì nó báo “Không tìm thấy dữ liệu khả dụng”

    • Đó không phải là vấn đề kích thước hay độ dài của mã QR, mà vì trình quét mặc định của iPhone không hỗ trợ URL URI data:
      Ví dụ, một trang web tự chứa Hi! có thể được mã hóa thành data:text/html;base64,PGh0bWw+PGJvZHk+SGkhPC9ib2R5PjwvaHRtbD4=, và nếu dán vào trình duyệt thì Hi! sẽ được render
      Nhưng nếu tạo nó thành mã QR thì trong tình huống đó sẽ không hoạt động
    • Cảm ơn đã kiểm tra
      Hầu hết điện thoại không đọc tốt các mã QR lớn, nên cần thứ như https://qrscanner.org/
      Và nó có lẽ sẽ không hoạt động trên điện thoại; do giới hạn kích thước nên tôi không thể đưa cả khả năng tương thích đó vào
    • Việc nó không chạy trên iPhone lại khiến tôi hơi yên tâm
      Tôi thường quét các mã QR dán khắp nơi để tiết kiệm thời gian nhập URL, nên nghĩ đến việc chỉ quét mã QR mà có thể thực thi mã tùy ý thì khá đáng sợ
  • Nếu thêm image-rendering: pixelated vào CSS của canvas, có lẽ nó sẽ trông có cảm giác pixel sắc nét thay vì bị nhòe

    • Tôi đã thử, nhưng thấy giao diện hiện tại thú vị hơn và có cảm giác retro hơn
  • Dự án tiếp theo hy vọng sẽ là LLM dạng mã QR
    Liên quan: https://www.reddit.com/r/OpenAI/comments/138kbhs/someone_sho...

  • Liên kết trailer của trò chơi dẫn đến một Shorts tên “Fly me to the moon - 19 September 2024”
    Có vẻ là nhầm lẫn

    • Giờ chắc đã được sửa rồi
  • Tôi thật sự thích những dự án game siêu nhỏ như thế này
    Nó làm tôi nhớ đến .kkrieger
    https://en.wikipedia.org/wiki/.kkrieger

    • Khi tôi đăng lên LinkedIn, có người đã cho tôi biết về nó; thật sự rất tuyệt
  • Mong bạn tiếp tục làm ra những thứ hay ho, kuberwastaken

    • Tôi sẽ cố hết sức
  • Tôi từng nói chuyện với một người bạn về một ý tưởng có phần liên quan
    Tôi tự hỏi liệu có thể mã hóa toàn bộ tệp STL dùng cho in 3D vào mã QR rồi dán lên vật thể thật, để chỉ cần quét món đồ đã tạo là có thể in lại nó không
    Tìm hiểu thì có vẻ dữ liệu quá nhiều, và tôi còn tìm cả mã QR nhiều màu, nhưng không biết là có thể tạo mã QR lớn hơn

    • Trước đây tôi từng làm một thứ tương tự cho bàn, như một dạng khám phá thiết kế
      Vì bàn chỉ cần cắt tấm vật liệu nên tôi mã hóa tệp 2D, nhưng ngay cả vậy, để chứng minh ý tưởng tôi vẫn phải dùng đến thuật toán nén tùy chỉnh
      https://johnkestner.com/rev/