Bỏ qua tới nội dung
Các trang tài liệu

Nhà phát triển · Hướng dẫn

Yêu cầu với game

Ràng buộc về bundle, mạng, dữ liệu, iframe, màn hình, tải, âm thanh và tạm dừng, kèm checklist trước khi nộp.

Trên trang này

Những yêu cầu dưới đây giúp game chạy ổn trên mọi thiết bị, tải nhanh và không ảnh hưởng tới game khác trên cùng origin. Phần lớn được kiểm tự động bằng wsg validate và wsg build lúc phát hành; phần còn lại được đội vận hành kiểm tra khi duyệt.

Cấu trúc bundle

Bundle là một thư mục tĩnh, có index.html ở gốc:

Thư mục build
dist/
├─ index.html          bắt buộc, ở gốc thư mục build
├─ game.js
├─ assets/
│  ├─ sprites.webp
│  └─ music.ogg
└─ ...
  • Đường dẫn tương đối. Bundle được phục vụ dưới https://games.leonogames.com/<slug>/<version>/, nên mọi file phải tải bằng đường dẫn tương đối (./game.js, assets/music.ogg), không bao giờ bằng đường dẫn tuyệt đối kiểu /assets/.... Với Vite, đặt base: './'; với bundler khác, đặt public path về rỗng hoặc ./.
  • Ngoại lệ duy nhất là file SDK, tải bằng đường dẫn gốc /sdk/v1/wsg-sdk.js.
  • Kích thước: tổng tối đa 20 MB và 300 file; index.html tối đa 200 KB. wsg build cảnh báo khi bundle vượt 3 MB; hãy nhắm dưới 3 MB để tải nhanh trên 4G.
  • Kiểu file. Origin game trả Content-Type theo đuôi file: HTML, JS, CSS, JSON, ảnh (png, jpg, webp, avif, gif, svg), âm thanh (mp3, ogg, m4a, wav), video (mp4, webm), font (woff2, woff, ttf, otf), wasm (application/wasm) và vài định dạng của engine (atlas, fnt, glsl, bin). Đuôi khác được trả về như application/octet-stream. Origin game không tự gắn Content-Encoding, nên đừng nộp file nén sẵn .br hay .gz để trình duyệt tự giải nén.
  • Bất biến. Một phiên bản đã phát hành không bao giờ thay đổi và được cache một năm. Sửa lỗi là phát hành phiên bản mới.

Không gọi ra origin khác

Game chỉ được tải tài nguyên từ chính bundle của nó và file SDK. Font, thư viện từ CDN, analytics, SDK quảng cáo bên thứ ba, cấu hình từ xa… đều phải đóng gói vào bundle hoặc bỏ đi.

wsg build quét index.html và mọi file .js tìm URL dạng http:// hoặc https:// không thuộc origin game hay SDK, và báo cảnh báo (--strict thì thành lỗi). Chuỗi URL không bao giờ được gọi (namespace XML, banner thư viện) cũng bị liệt kê; đội vận hành xem từng trường hợp khi duyệt.

Lưu ý

Game cần server riêng (chơi mạng, lưu đám mây riêng) phải thoả thuận trước với đội vận hành. Server đó phải bật CORS cho origin https://games.leonogames.com và xác thực người chơi bằng token của portal. Xem Xác thực người chơi.

Dữ liệu người chơi

  • Dữ liệu cần giữ (kỷ lục, tiến độ, cài đặt) lưu bằng WSG.storage: gắn với người chơi và với game, tối đa 100 KB.
  • Origin game dùng chung cho mọi game. localStorage, sessionStorage và IndexedDB trên origin này bị game khác đọc và ghi được, và có thể bị trình duyệt xoá. Chỉ dùng chúng làm bộ nhớ đệm, đặt tiền tố bằng slug cho key (tap-rush:cache).
  • Không dùng document.cookie.

Hành vi trong iframe

Portal nhúng game với các thuộc tính sau:

HTML
<iframe
  src="https://games.leonogames.com/<slug>/<version>/index.html?wsg=1&host=<origin portal>&lang=<vi|en>&v=<version>"
  sandbox="allow-scripts allow-same-origin allow-pointer-lock allow-forms"
  allow="autoplay; fullscreen; gamepad; clipboard-write; accelerometer; gyroscope"
  referrerpolicy="strict-origin"
></iframe>

Hệ quả cho game:

  • Không popup: window.open() và link target="_blank" không mở được gì. Chia sẻ dùng WSG.share().
  • Không điều hướng trang cha: gán window.top.location bị chặn. Đừng truy cập window.top hay window.parent; mọi thứ đi qua SDK.
  • Không hộp thoại hệ thống: alert(), confirm(), prompt() không hiện. Tự vẽ hộp thoại trong game.
  • Không tải file xuống, không khoá hướng màn hình (screen.orientation.lock() thất bại), không camera, micro hay vị trí.
  • Được phép: toàn màn hình, tay cầm, cảm biến chuyển động, ghi clipboard, khoá con trỏ chuột, form.
  • Giữ nguyên URL. Đừng chuyển hướng sang trang khác trong bundle: query wsg, host sẽ mất và SDK rơi về standalone.

Khung iframe trên portal theo orientation trong game.json: portrait là 9:16, landscape là 16:9, any lấp đầy vùng chơi. Trên điện thoại, portal có nút "Toàn màn hình" cho khung chơi.

Màn hình và điều khiển

  • Chạy tốt ở mọi khung từ 320×568 tới 1920×1080 và khi khung đổi kích thước (xoay máy, bật toàn màn hình). Nghe sự kiện resize.
  • Không cuộn trang, không chọn chữ, không zoom. Dùng thẻ meta và CSS như sau:
HTML
<meta
  name="viewport"
  content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, viewport-fit=cover"
/>
<style>
  html,
  body {
    margin: 0;
    height: 100%;
    overflow: hidden;
    touch-action: none;
    user-select: none;
    -webkit-user-select: none;
  }
</style>
  • Tôn trọng vùng an toàn (tai thỏ, thanh điều hướng) bằng env(safe-area-inset-top), env(safe-area-inset-bottom)…, đặc biệt khi game chạy toàn màn hình. Đặt nút quan trọng cách mép.
  • Hỗ trợ đủ các kiểu điều khiển khai báo trong controls. Vùng chạm tối thiểu khoảng 44 px.
  • Chữ trong game theo WSG.getLocale(); portal hiện có tiếng Việt và tiếng Anh.

Tải nhanh

  • Vào được menu trong vòng 3 giây trên mạng 4G. Báo tiến độ bằng loadingProgress() và gọi loadingFinished() khi sẵn sàng; portal che game bằng overlay tải cho tới lúc đó (tối đa 30 giây).
  • Giữ bundle nhỏ: nén ảnh (WebP), âm thanh ngắn và nén (OGG, M4A, MP3), tải màn sau khi cần thay vì tải hết từ đầu.
  • Không khoá luồng chính quá lâu lúc khởi động; giới hạn devicePixelRatio (ví dụ tối đa 2) để máy yếu không bị ì.

Âm thanh

  • Chỉ phát âm thanh sau lần chạm hoặc click đầu tiên của người chơi (iOS và chính sách autoplay của trình duyệt). Tạo hoặc resume() AudioContext ngay trong xử lý sự kiện chạm.
  • Tắt tiếng khi nhận audio(false) hoặc pause; bật lại khi audio(true) hoặc resume, nhưng vẫn tôn trọng lựa chọn tắt tiếng của người chơi.
  • Có nút tắt tiếng trong game và lưu lựa chọn bằng WSG.storage.

Tạm dừng

  • Khi nhận pause (tab bị ẩn, sắp có quảng cáo): dừng vòng lặp game, đồng hồ, vật lý, timer, và tắt tiếng.
  • Khi nhận resume: chạy tiếp mà không tính quãng thời gian đã dừng. Nếu game nhịp nhanh, cân nhắc hiện màn "Chạm để chơi tiếp" thay vì chạy ngay.
  • Kiểm thử bằng cách chuyển tab: SDK phát pause/resume cả ở chế độ standalone.

Không lỗi console

Luồng chơi bình thường không được có lỗi trong console. Lỗi hay gặp:

  • favicon.ico 404: thêm <link rel="icon" href="data:," /> vào <head>.
  • Asset 404 do đường dẫn tuyệt đối hoặc sai hoa thường (origin game phân biệt hoa thường).
  • Promise bị reject mà không bắt, ví dụ WSG.storage.set() vượt giới hạn.
  • Tài nguyên http:// bị chặn trên trang https:// (mixed content).

Checklist trước khi nộp

  • index.html ở gốc thư mục build; mọi đường dẫn tương đối; SDK nhúng bằng /sdk/v1/wsg-sdk.js.
  • Không request tới origin nào khác.
  • Bundle tối đa 20 MB (nên dưới 3 MB), tối đa 300 file, index.html tối đa 200 KB.
  • await WSG.init({ gameId: '<slug>' }) trước mọi lời gọi khác.
  • loadingFinished() khi vào menu; vào menu trong 3 giây trên 4G.
  • gameplayStart() khi người chơi điều khiển, gameplayStop() khi hết lượt; nộp điểm trong 10 giây sau đó; điểm là số nguyên không âm.
  • limits tính từ thiết kế; điểm trong game không vượt maxScore.
  • Dừng và tắt tiếng khi pause hay audio(false); chạy lại khi resume.
  • Rewarded chỉ thưởng khi rewarded === true; interstitial bỏ qua được cooldown.
  • Dữ liệu cần giữ dùng WSG.storage; không cookie; localStorage chỉ làm bộ nhớ đệm, key có tiền tố slug.
  • Không popup, không alert(), không điều hướng trang cha, không chuyển sang URL khác.
  • Chạy tốt từ 320×568 tới 1920×1080, đúng orientation, không cuộn, không zoom, tôn trọng vùng an toàn.
  • Âm thanh chỉ phát sau lần chạm đầu tiên.
  • Không lỗi console khi chơi bình thường (kiểm tra ở chế độ standalone).
  • thumbnail.png 512×512, tối đa 150 KB; game.json qua wsg validate.
  • Có test hooks window.__WSG_TEST__ (khuyến nghị, xem Kiểm thử).