diff --git a/wasm/fragments/start_later.js b/wasm/fragments/start_later.js deleted file mode 100644 index 7bac1cdeb..000000000 --- a/wasm/fragments/start_later.js +++ /dev/null @@ -1,9 +0,0 @@ -/* DELETE -;run\(\); -*/ - - -/* DELETE -if ?\(!calledRun\)\s*?run\(\); -*/ - diff --git a/wasm/web/index.html b/wasm/web/index.html index 55f98b96d..e5628e4f1 100644 --- a/wasm/web/index.html +++ b/wasm/web/index.html @@ -1,35 +1,97 @@ - - + + + + SuperTuxKart + + + -
-
- -

Downloading game files...

+
+
+ +

SuperTuxKart Wasm

+
+

This is an experimental port of SuperTuxKart to the browser using WebAssembly and Emscripten. Currently, everything works except for some rendering APIs and networking.

+

There is a 700MB initial download required to play, and the game will require around 1GB of memory.

+

This web port was made by ading2210, and the source code is located at github.com/ading2210/stk-code.

+

If you want to check on the status of this port, take a look at the corresponding pull request in the SuperTuxKart repository.

+
+ +

+
-

This web port was made by ading2210.

-

The source code is located at github.com/ading2210/stk-code.

\ No newline at end of file diff --git a/wasm/web/script.js b/wasm/web/script.js index 95bd978df..5dcd27288 100644 --- a/wasm/web/script.js +++ b/wasm/web/script.js @@ -8,6 +8,7 @@ let idbfs_mount = null; let start_button = document.getElementById("start_button"); let status_text = document.getElementById("status_text"); +let info_container = document.getElementById("info_container"); function load_db() { if (db) return db; @@ -103,24 +104,33 @@ async function write_db_chunks(key, data) { } async function download_chunks(url) { + let path = url.split("/"); + let filename = path.pop(); + let base_url = path.join("/"); + + status_text.textContent = `Downloading manifest for ${filename}...`; let r1 = await fetch(url + ".manifest"); let manifest = (await r1.text()).split("\n"); let size = parseInt(manifest.shift()); manifest.pop(); - let path = url.split("/"); - path.pop(); - let base_url = path.join("/"); - let offset = 0; let chunk = null; let array = new Uint8Array(size); + let chunk_count = manifest.length; + let current_chunk = 1; + while (chunk = manifest.shift()) { + let mb_progress = Math.floor(offset / (1024 ** 2)) + let mb_total = Math.floor(size / (1024 ** 2)) + status_text.textContent = `Downloading ${filename}... (chunk ${current_chunk}/${chunk_count}, ${mb_progress}/${mb_total}MiB)`; + let r2 = await fetch(base_url + "/" + chunk); let buffer = await r2.arrayBuffer(); let chunk_array = new Uint8Array(buffer); array.set(chunk_array, offset); - offset += chunk_array.length; + offset += chunk_array.length; + current_chunk++; } return array.buffer; @@ -130,11 +140,12 @@ async function extract_tar(url, fs_path, use_cache = false) { //download tar file from server and decompress let decompressed; if (!use_cache || !await check_db(url)) { + let filename = url.split("/").pop(); let compressed = await download_chunks(url); decompressed = pako.inflate(compressed); compressed = null; if (use_cache) { - console.log("saving to cache"); + status_text.textContent = `Saving ${filename} to the cache...`; await write_db_chunks(url, decompressed); } } @@ -162,11 +173,8 @@ async function extract_tar(url, fs_path, use_cache = false) { } async function load_data() { - console.log("downloading and extracting game data"); await extract_tar("/game/data.tar.gz", "/data", true); - console.log("downloading and extracting assets"); await extract_tar("/game/assets.tar.gz", "/data", true); - console.log("done") } async function load_idbfs() { @@ -183,28 +191,41 @@ function sync_idbfs(populate = false) { }) } +function wait_for_frame() { + return new Promise((resolve) => {requestAnimationFrame(resolve)}); +} + async function main() { - await load_data(); + globalThis.ready = true; await load_idbfs(); - start_button.onclick = () => {requestAnimationFrame(start_game)}; + start_button.onclick = start_game; start_button.disabled = false; - status_text.textContent = "Ready"; } -function start_game() { +async function start_game() { + status_text.textContent = "Loading game files..."; start_button.disabled = true; - status_text.textContent = "Initializing"; - requestAnimationFrame(() => { - run(); - status_text.textContent = "Running"; - sync_idbfs(); - }); -} + await load_data(); + await wait_for_frame(); + status_text.textContent = "Launching game..."; -globalThis.pako = pako; -globalThis.jsUntar = jsUntar; -globalThis.load_data = load_data; -globalThis.sync_idbfs = sync_idbfs; + await wait_for_frame(); + run(); + info_container.style.zIndex = 0; + info_container.style.display = "none"; + sync_idbfs(); + + console.warn("Warning: Opening devtools may harm the game's performance."); +} Module["canvas"] = document.getElementById("canvas") -main(); \ No newline at end of file +globalThis.main = main; +globalThis.sync_idbfs = sync_idbfs; +globalThis.load_idbfs = load_idbfs; + +let poll_runtime_interval = setInterval(() => { + if (globalThis.ready) { + main(); + clearInterval(poll_runtime_interval); + } +}, 100); \ No newline at end of file diff --git a/wasm/web/supertuxkart_64.png b/wasm/web/supertuxkart_64.png new file mode 100644 index 000000000..6beb8e609 Binary files /dev/null and b/wasm/web/supertuxkart_64.png differ