Skip to main content

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 formStatus
BytecodeSupported. Recommended for release.
SourceSupported. Scripts are compiled when the page loads.
Embedded, Shared and Linked AOTNot 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:

FileWhat it is
index.htmlThe page players open
index.jsLoads the game
index.wasmThe game program
index.dataYour 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://localhost counts as secure; plain http:// 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 .c files are supported.
  • native.link_libraries is 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.

SettingValue
Memory768 MiB, reserved at startup; doesn't grow
Threads16 worker threads
GraphicsWebGL 2 only
SoundWebAudio
Page titlecTurtle
IconPNG only, from package.icon

Errors​

MessageWhat to do
WebAssembly supports loose scripts and bytecode; BT AOT emits x64 codeSet the web target's code form to Source or Bytecode.
WebAssembly cannot load desktop BT AOT code; use source or bytecodeYour game.json points at prebuilt AOT code. Use a manifest with bt.sources.
web SDK is missing or incompleteSee Web SDK.
Page loads, game doesn't start, crossOriginIsolated is falseThe server isn't sending the two headers, or the page isn't on HTTPS or localhost.