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:
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, đặtbase: './'; 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.htmltối đa 200 KB.wsg buildcả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-Typetheo đ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ắnContent-Encoding, nên đừng nộp file nén sẵn.brhay.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,sessionStoragevà 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:
<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à linktarget="_blank"không mở được gì. Chia sẻ dùngWSG.share(). - Không điều hướng trang cha: gán
window.top.locationbị chặn. Đừng truy cậpwindow.tophaywindow.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,hostsẽ 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:
<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ọiloadingFinished()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()AudioContextngay trong xử lý sự kiện chạm. - Tắt tiếng khi nhận
audio(false)hoặcpause; bật lại khiaudio(true)hoặcresume, 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/resumecả ở 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.ico404: 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 tranghttps://(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.htmltố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. -
limitstính từ thiết kế; điểm trong game không vượtmaxScore. - Dừng và tắt tiếng khi
pausehayaudio(false); chạy lại khiresume. - Rewarded chỉ thưởng khi
rewarded === true; interstitial bỏ qua đượccooldown. - Dữ liệu cần giữ dùng
WSG.storage; không cookie;localStoragechỉ 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.png512×512, tối đa 150 KB;game.jsonquawsg validate. - Có test hooks
window.__WSG_TEST__(khuyến nghị, xem Kiểm thử).