Skip to content

Instantly share code, notes, and snippets.

@jakobbouchard
Created September 26, 2023 22:01
Show Gist options
  • Save jakobbouchard/dc0d44cc1f18642eafa40acd9b9780e6 to your computer and use it in GitHub Desktop.
Save jakobbouchard/dc0d44cc1f18642eafa40acd9b9780e6 to your computer and use it in GitHub Desktop.
Custom Godot HTML5 shell
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, user-scalable=no" />
<title>$GODOT_PROJECT_NAME</title>
<style>
body {
touch-action: none;
margin: 0;
border: 0;
padding: 0;
/* For pixel-art scaling */
image-rendering: pixelated;
width: 100vw;
height: 100vh;
background-color: #000000;
}
#app {
margin: auto;
background-repeat: no-repeat;
background-size: cover;
width: calc(160 * var(--pixel-size));
height: 100vh; /* "144px" */
}
#canvas:focus {
outline: none;
}
#status {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
visibility: hidden;
}
#status-progress {
display: block;
box-sizing: border-box;
border: calc(1 * var(--pixel-size)) solid #4d4d80;
width: calc(50 * var(--pixel-size));
height: calc(6 * var(--pixel-size));
background-color: transparent;
visibility: visible;
}
#status-progress-inner {
box-sizing: border-box;
width: 0;
height: 100%;
background-color: #e6a1cf;
}
#status-notice {
display: flex;
align-items: center;
justify-content: center;
border: calc(1 * var(--pixel-size)) solid #e6a1cf;
width: calc(100 * var(--pixel-size));
height: calc(24 * var(--pixel-size));
background-color: #4d4d80;
color: #ffe6ea;
text-align: center;
line-height: 1.5;
font-family: monospace;
font-size: calc(3.5 * var(--pixel-size));
visibility: visible;
}
</style>
<script>
// Add a custom CSS variable to get a "pixel" size in CSS
document.documentElement.style.setProperty(
"--pixel-size",
`${window.innerHeight / 144}px`
);
const GODOT_CONFIG = $GODOT_CONFIG;
const style = document.createElement("style");
style.textContent = `#app { background-image: url("${GODOT_CONFIG.executable}.png") }`;
document.head.append(style);
</script>
$GODOT_HEAD_INCLUDE
</head>
<body>
<div id="app">
<canvas style="display: none" id="canvas"></canvas>
<div id="status">
<div
id="status-progress"
style="display: none"
oncontextmenu="event.preventDefault();"
>
<div id="status-progress-inner"></div>
</div>
<div id="status-notice" style="display: none"></div>
</div>
</div>
<script src="$GODOT_URL"></script>
<script>
const engine = new Engine(GODOT_CONFIG);
(function () {
const statusProgress = document.getElementById("status-progress");
const statusProgressInner = document.getElementById(
"status-progress-inner"
);
const statusNotice = document.getElementById("status-notice");
const canvas = document.getElementById("canvas");
let initializing = true;
let statusMode = "hidden";
function setStatusMode(mode) {
if (statusMode === mode || !initializing) {
return;
}
[statusProgress, statusNotice].forEach((elem) => {
elem.style.display = "none";
});
switch (mode) {
case "progress":
statusProgress.style.display = "";
break;
case "notice":
statusNotice.style.display = "";
break;
case "hidden":
break;
default:
throw new Error("Invalid status mode");
}
statusMode = mode;
}
function displayFailureNotice(err) {
setStatusMode("notice");
initializing = false;
const msg = err.message || err;
console.error(msg);
while (statusNotice.lastChild) {
statusNotice.removeChild(statusNotice.lastChild);
}
msg.split("\n").forEach((line) => {
statusNotice.appendChild(document.createTextNode(line));
statusNotice.appendChild(document.createElement("br"));
});
}
const missing = Engine.getMissingFeatures();
if (missing.length !== 0) {
console.error(
"The following features required to run Godot projects on the Web are missing:\n" +
missing.join("\n")
);
displayFailureNotice("Your browser is missing required features.");
return;
}
if (
navigator.platform.indexOf("Mac") === 0 ||
navigator.platform === "iPhone"
) {
displayFailureNotice("macOS and iOS browsers are not supported.\nPlease download the native version.");
return;
}
engine
.startGame({
onProgress: function (current, total) {
setStatusMode("progress");
if (total > 0) {
if (current === total) {
statusProgressInner.style.width = "100%";
return;
}
const pixels = Math.floor((current / total) * 48);
statusProgressInner.style.width = `calc(${pixels} * var(--pixel-size))`;
}
},
onExit: function (code) {
canvas.style.display = "none";
if (code !== 0) {
displayFailureNotice(`Process exited with code ${code}`);
}
},
})
.then(() => {
setStatusMode("hidden");
initializing = false;
canvas.style.display = "block";
}, displayFailureNotice);
})();
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment