Web
Publish your game as a web page that runs in the browser.
Building
In Studio, use the WebAssembly target in Build Settings → Targets. Its
default output is build/web/index.html. From a terminal:
ctgame build --target "WebAssembly" MyGame.ctproject
or, without a project file:
ctgame build --wasm -o build/web/index.html game.json
Web builds can be made on Windows or Linux. Everything needed comes with cTurtle's web SDK.
| Code form | Status |
|---|---|
| Bytecode | Supported. Recommended for release. |
| Source | Supported. Scripts are compiled when the page loads. |
| Embedded, Shared and Linked AOT | Not supported. AOT produces desktop machine code. |
On the web, BT code always runs in the interpreter; there is no JIT. Expect scripts to run slower than in a desktop build.
Output
For an output of build/web/index.html you get:
| File | What it is |
|---|---|
index.html | The page players open |
index.js | Loads the game |
index.wasm | The game program |
index.data | Your game's files: scripts, data, images, sounds |
Upload all four together, from the same build, to the same folder. Mixing files from different builds stops the game from loading. Other files already in the output folder are left alone.
The whole .data file downloads before the game starts, so its size is the
player's loading time.
Hosting requirements
The game uses several threads, and browsers only allow that on pages that are cross-origin isolated. You make a page cross-origin isolated by having your web server send two headers with the page and its files:
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp
You also need:
- HTTPS. Browsers allow threads only on secure pages.
http://localhostcounts as secure; plainhttp://to any other address does not, even on your own network. - The right file type for
.wasm:Content-Type: application/wasm. With the wrong type the game still loads, but more slowly.
Without the headers or HTTPS the page loads but the game fails to start. In the
browser's developer console, crossOriginIsolated is false.
Opening index.html straight from disk (file://) does not work. Use a web
server, even for local testing.
The require-corp header blocks files from other websites unless they opt in.
Serve everything the page loads from your own site. Requests your game makes to
web APIs (with CORS) are not affected.
Setting the headers
nginx
location /mygame/ {
add_header Cross-Origin-Opener-Policy same-origin;
add_header Cross-Origin-Embedder-Policy require-corp;
types { application/wasm wasm; }
}
Apache (.htaccess, needs mod_headers)
Header set Cross-Origin-Opener-Policy "same-origin"
Header set Cross-Origin-Embedder-Policy "require-corp"
AddType application/wasm .wasm
Caddy
header {
Cross-Origin-Opener-Policy same-origin
Cross-Origin-Embedder-Policy require-corp
}
Static hosts. Netlify and Cloudflare Pages read a _headers file placed
next to index.html:
/*
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp
Hosts that don't let you set response headers, such as GitHub Pages, can't run the game.
Testing locally
Use wasm-serve. It sends the right headers and file
types:
wasm-serve build/web --port 8080
Then open http://localhost:8080/ in a browser on the same computer. Don't
open it from another device by IP address: that isn't a secure page, so the
game won't start.
Your own C code
Games with their own C code (Adding C code) work on the web.
The C is compiled into index.wasm with the web SDK's compiler; you don't need
CMake or a desktop C compiler for this.
- Only
.cfiles are supported. native.link_librariesis ignored for web builds.- If your scripts call functions your C code adds, use the Source code form. With Bytecode those scripts fail to compile, because web bytecode builds can't see your C functions. Studio picks Source for new web targets of such games.
Fixed settings
These are the same for every web game and can't be changed per game.
| Setting | Value |
|---|---|
| Memory | 768 MiB, reserved at startup; doesn't grow |
| Threads | 16 worker threads |
| Graphics | WebGL 2 only |
| Sound | WebAudio |
| Page title | cTurtle |
| Icon | PNG only, from package.icon |
Errors
| Message | What to do |
|---|---|
WebAssembly supports loose scripts and bytecode; BT AOT emits x64 code | Set the web target's code form to Source or Bytecode. |
WebAssembly cannot load desktop BT AOT code; use source or bytecode | Your game.json points at prebuilt AOT code. Use a manifest with bt.sources. |
web SDK is missing or incomplete | See Web SDK. |
Page loads, game doesn't start, crossOriginIsolated is false | The server isn't sending the two headers, or the page isn't on HTTPS or localhost. |