This commit is contained in:
1 parent
8855d36684
commit
73baba74b1
10 files changed
+4565
No files matched your search
@@ -0,0 +1,575 @@
|
||||
const UI = (function () {
|
||||
const $ = function (id) { return document.getElementById(id); };
|
||||
const screens = {
|
||||
welcome: $("screen-welcome"),
|
||||
map: $("screen-map"),
|
||||
level: $("screen-level"),
|
||||
finale: $("screen-finale")
|
||||
};
|
||||
|
||||
const topbar = $("topbar");
|
||||
const homeBtn = $("home-btn");
|
||||
const progressLabel = $("progress-label");
|
||||
const progressFill = $("progress-fill");
|
||||
const muteBtn = $("mute-btn");
|
||||
const revealOverlay = $("reveal-overlay");
|
||||
const confirmOverlay = $("confirm-overlay");
|
||||
const toastNode = $("toast");
|
||||
|
||||
const LEVEL_ICONS = { 1: "🌱", 2: "✨", 3: "⭐", 4: "🍰", 5: "💐", 6: "🃏", 7: "🍂" };
|
||||
|
||||
const SOUNDS = {
|
||||
click: [{ f: 520, d: 0.08, g: 0.025 }],
|
||||
seed: [{ f: 392, d: 0.1 }, { f: 523, d: 0.14, at: 0.08 }],
|
||||
water: [{ f: 660, d: 0.12 }, { f: 880, d: 0.18, at: 0.1 }],
|
||||
catch: [{ f: 784, d: 0.1 }, { f: 1046, d: 0.2, at: 0.08 }],
|
||||
star: [{ f: 880, d: 0.1 }, { f: 1174, d: 0.2, at: 0.09 }],
|
||||
place: [{ f: 523, d: 0.08 }, { f: 659, d: 0.13, at: 0.07 }],
|
||||
nope: [{ f: 330, d: 0.12, g: 0.022 }],
|
||||
chime: [{ f: 659, d: 0.12 }, { f: 988, d: 0.22, at: 0.1 }],
|
||||
complete: [
|
||||
{ f: 523, d: 0.16 },
|
||||
{ f: 659, d: 0.16, at: 0.12 },
|
||||
{ f: 784, d: 0.16, at: 0.24 },
|
||||
{ f: 1046, d: 0.34, at: 0.36 }
|
||||
],
|
||||
reveal: [
|
||||
{ f: 659, d: 0.16 },
|
||||
{ f: 784, d: 0.16, at: 0.11 },
|
||||
{ f: 988, d: 0.2, at: 0.22 },
|
||||
{ f: 1318, d: 0.38, at: 0.34 }
|
||||
]
|
||||
};
|
||||
|
||||
let state = { unlocked: 1, completed: [], revealed: [] };
|
||||
let currentScreen = "welcome";
|
||||
let muted = Storage.loadMuted();
|
||||
let audioContext = null;
|
||||
let toastTimer = 0;
|
||||
let revealCallback = null;
|
||||
let revealSteamCallback = null;
|
||||
let revealLastFocus = null;
|
||||
let confirmCallback = null;
|
||||
let confirmLastFocus = null;
|
||||
|
||||
function el(tag, className, text) {
|
||||
const node = document.createElement(tag);
|
||||
if (className) node.className = className;
|
||||
if (text !== undefined) node.textContent = text;
|
||||
return node;
|
||||
}
|
||||
|
||||
function escapeHtml(value) {
|
||||
return String(value).replace(/[&<>"']/g, function (character) {
|
||||
return {
|
||||
"&": "&",
|
||||
"<": "<",
|
||||
">": ">",
|
||||
'"': """,
|
||||
"'": "'"
|
||||
}[character];
|
||||
});
|
||||
}
|
||||
|
||||
function ensureAudio() {
|
||||
if (!window.AudioContext && !window.webkitAudioContext) return null;
|
||||
if (!audioContext) {
|
||||
const Ctor = window.AudioContext || window.webkitAudioContext;
|
||||
audioContext = new Ctor();
|
||||
}
|
||||
if (audioContext.state === "suspended") {
|
||||
audioContext.resume().catch(function () {});
|
||||
}
|
||||
return audioContext;
|
||||
}
|
||||
|
||||
function play(name) {
|
||||
if (muted) return;
|
||||
const context = ensureAudio();
|
||||
if (!context) return;
|
||||
const parts = SOUNDS[name] || SOUNDS.click;
|
||||
|
||||
parts.forEach(function (part) {
|
||||
const start = context.currentTime + (part.at || 0);
|
||||
const oscillator = context.createOscillator();
|
||||
const gain = context.createGain();
|
||||
oscillator.type = "sine";
|
||||
oscillator.frequency.setValueAtTime(part.f, start);
|
||||
gain.gain.setValueAtTime(0.0001, start);
|
||||
gain.gain.exponentialRampToValueAtTime(part.g || 0.035, start + 0.015);
|
||||
gain.gain.exponentialRampToValueAtTime(0.0001, start + part.d);
|
||||
oscillator.connect(gain);
|
||||
gain.connect(context.destination);
|
||||
oscillator.start(start);
|
||||
oscillator.stop(start + part.d + 0.06);
|
||||
});
|
||||
}
|
||||
|
||||
function updateMuteButton() {
|
||||
muteBtn.textContent = muted ? "Geluid uit" : "Geluid aan";
|
||||
muteBtn.setAttribute("aria-pressed", muted ? "true" : "false");
|
||||
muteBtn.setAttribute(
|
||||
"aria-label",
|
||||
muted ? "Geluid staat uit. Zet geluid aan." : "Geluid staat aan. Zet geluid uit."
|
||||
);
|
||||
}
|
||||
|
||||
function toggleMute() {
|
||||
muted = !muted;
|
||||
Storage.saveMuted(muted);
|
||||
updateMuteButton();
|
||||
if (!muted) play("chime");
|
||||
}
|
||||
|
||||
function updateProgress() {
|
||||
const completed = state.completed.length;
|
||||
const total = totalLevels();
|
||||
progressLabel.textContent = completed + " / " + total + " cadeaus";
|
||||
progressFill.style.width = (completed / total) * 100 + "%";
|
||||
}
|
||||
|
||||
function totalLevels() {
|
||||
return Levels.count || (GAME_CONFIG.games ? GAME_CONFIG.games.length : 5);
|
||||
}
|
||||
|
||||
function setState(nextState) {
|
||||
state = nextState;
|
||||
updateProgress();
|
||||
const startBtn = $("start-btn");
|
||||
if (startBtn) {
|
||||
startBtn.textContent = state.completed.length > 0 ? "Verder in de tuin" : "Begin in de tuin";
|
||||
}
|
||||
}
|
||||
|
||||
function showScreen(name) {
|
||||
Object.keys(screens).forEach(function (key) {
|
||||
screens[key].hidden = key !== name;
|
||||
});
|
||||
currentScreen = name;
|
||||
topbar.hidden = name === "welcome";
|
||||
homeBtn.hidden = name !== "level";
|
||||
updateProgress();
|
||||
window.scrollTo(0, 0);
|
||||
}
|
||||
|
||||
function setHint(message) {
|
||||
const node = $("level-hint");
|
||||
node.textContent = message || "";
|
||||
}
|
||||
|
||||
function showLevel(id) {
|
||||
const info = Levels.meta[id];
|
||||
$("level-eyebrow").textContent = "Tuintaak " + id + " van " + totalLevels();
|
||||
$("level-title").textContent = info.title;
|
||||
$("level-instruction").textContent = info.instruction;
|
||||
setHint("");
|
||||
showScreen("level");
|
||||
}
|
||||
|
||||
function getCoverUrl(game) {
|
||||
if (!game) return "";
|
||||
if (game.image) return game.image;
|
||||
if (game.appId) {
|
||||
return "https://cdn.cloudflare.steamstatic.com/steam/apps/" + game.appId + "/header.jpg";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
function getActivationUrl(key) {
|
||||
return "https://store.steampowered.com/account/registerkey?key=" + encodeURIComponent(key);
|
||||
}
|
||||
|
||||
function copyKey() {
|
||||
const input = $("reveal-key-value");
|
||||
const value = input.value.trim();
|
||||
if (!value) return;
|
||||
|
||||
const button = $("reveal-key-copy");
|
||||
const done = function () {
|
||||
button.textContent = "Gekopieerd";
|
||||
toast("Steam-key gekopieerd.");
|
||||
window.setTimeout(function () { button.textContent = "Kopieer"; }, 1800);
|
||||
};
|
||||
const fallback = function () {
|
||||
input.focus();
|
||||
input.select();
|
||||
let succeeded = false;
|
||||
try {
|
||||
succeeded = document.execCommand("copy");
|
||||
} catch (error) {
|
||||
succeeded = false;
|
||||
}
|
||||
if (succeeded) {
|
||||
done();
|
||||
} else {
|
||||
button.textContent = "Selecteer";
|
||||
toast("De key is geselecteerd. Kopieer hem met Ctrl+C.");
|
||||
}
|
||||
};
|
||||
|
||||
if (navigator.clipboard && typeof navigator.clipboard.writeText === "function") {
|
||||
navigator.clipboard.writeText(value).then(done).catch(fallback);
|
||||
} else {
|
||||
fallback();
|
||||
}
|
||||
}
|
||||
|
||||
function coverArt(game, className) {
|
||||
const wrap = el("span", className);
|
||||
wrap.style.setProperty("--accent", (game && game.accent) || "#d9c2e8");
|
||||
wrap.append(el("span", "cover-fallback", (game && game.title) || "Cadeau"));
|
||||
|
||||
const url = getCoverUrl(game);
|
||||
if (url) {
|
||||
const img = document.createElement("img");
|
||||
img.alt = "";
|
||||
img.loading = "lazy";
|
||||
img.src = url;
|
||||
img.addEventListener("load", function () { wrap.classList.add("has-image"); });
|
||||
img.addEventListener("error", function () { img.remove(); });
|
||||
wrap.append(img);
|
||||
}
|
||||
return wrap;
|
||||
}
|
||||
|
||||
function renderMap() {
|
||||
const path = $("garden-path");
|
||||
path.innerHTML = "";
|
||||
const total = totalLevels();
|
||||
|
||||
for (let level = 1; level <= total; level += 1) {
|
||||
const completed = state.completed.indexOf(level) !== -1;
|
||||
const revealed = state.revealed.indexOf(level - 1) !== -1;
|
||||
const unlocked = level <= state.unlocked || completed;
|
||||
const isCurrent = !completed && level === state.unlocked;
|
||||
|
||||
const node = el("button", "map-node");
|
||||
node.type = "button";
|
||||
node.disabled = !unlocked;
|
||||
node.classList.toggle("completed", completed);
|
||||
node.classList.toggle("current", isCurrent);
|
||||
node.classList.toggle("locked", !unlocked);
|
||||
|
||||
let sub = "Nog even";
|
||||
if (completed && revealed) sub = "Cadeau geopend";
|
||||
else if (completed) sub = "Cadeau wacht";
|
||||
else if (isCurrent) sub = "Speel nu";
|
||||
|
||||
node.innerHTML =
|
||||
'<span class="node-circle">' +
|
||||
'<span class="node-icon" aria-hidden="true">' + LEVEL_ICONS[level] + "</span>" +
|
||||
(revealed ? '<span class="node-gift" aria-hidden="true">🎁</span>' : "") +
|
||||
(!unlocked ? '<span class="node-lock" aria-hidden="true">🔒</span>' : "") +
|
||||
"</span>" +
|
||||
'<span class="node-text">' +
|
||||
'<span class="node-label">Level ' + level + "</span>" +
|
||||
'<span class="node-sub">' + sub + "</span>" +
|
||||
"</span>";
|
||||
|
||||
node.setAttribute(
|
||||
"aria-label",
|
||||
"Level " + level + ", " + Levels.meta[level].title + ", " + sub + (unlocked ? "" : ", nog vergrendeld")
|
||||
);
|
||||
node.addEventListener("click", function () { App.startLevel(level); });
|
||||
path.append(node);
|
||||
}
|
||||
|
||||
renderShelf();
|
||||
$("finale-btn").hidden = state.completed.length !== total || state.revealed.length !== total;
|
||||
updateProgress();
|
||||
}
|
||||
|
||||
function renderShelf() {
|
||||
const grid = $("gift-shelf");
|
||||
grid.innerHTML = "";
|
||||
const games = GAME_CONFIG.games || [];
|
||||
const total = totalLevels();
|
||||
|
||||
for (let index = 0; index < total; index += 1) {
|
||||
const game = games[index];
|
||||
const revealed = state.revealed.indexOf(index) !== -1 && Boolean(game);
|
||||
|
||||
if (!revealed) {
|
||||
const card = el("div", "shelf-card locked");
|
||||
card.innerHTML =
|
||||
'<span class="gift-box" aria-hidden="true">🎁</span>' +
|
||||
'<span class="shelf-title">Cadeau ' + (index + 1) + "</span>" +
|
||||
'<span class="shelf-sub">Nog verborgen</span>';
|
||||
card.setAttribute("aria-label", "Cadeau " + (index + 1) + ", nog verborgen");
|
||||
grid.append(card);
|
||||
continue;
|
||||
}
|
||||
|
||||
const card = el("button", "shelf-card");
|
||||
card.type = "button";
|
||||
card.append(coverArt(game, "shelf-art"));
|
||||
card.append(el("span", "shelf-title", game.title));
|
||||
card.setAttribute("aria-label", "Bekijk cadeau: " + game.title);
|
||||
card.addEventListener("click", function () {
|
||||
showReveal(index, null, { review: true });
|
||||
});
|
||||
grid.append(card);
|
||||
}
|
||||
}
|
||||
|
||||
function showReveal(index, onContinue, options) {
|
||||
const opts = options || {};
|
||||
const review = Boolean(opts.review);
|
||||
const game = (GAME_CONFIG.games && GAME_CONFIG.games[index]) || {
|
||||
title: "Een geheim cadeau",
|
||||
note: "Dit cadeau is nog niet ingevuld in de configuratie.",
|
||||
accent: "#d9c2e8"
|
||||
};
|
||||
|
||||
revealLastFocus = document.activeElement;
|
||||
$("reveal-eyebrow").textContent = review ? "Jouw cadeau" : "Cadeau ontgrendeld";
|
||||
$("reveal-title").textContent = game.title;
|
||||
$("reveal-note").textContent = game.note || "Speciaal voor jou uitgekozen.";
|
||||
|
||||
const key = typeof game.key === "string" ? game.key.trim() : "";
|
||||
const keyBox = $("reveal-key");
|
||||
const keyValue = $("reveal-key-value");
|
||||
keyBox.hidden = !key;
|
||||
keyValue.value = key;
|
||||
$("reveal-key-copy").textContent = "Kopieer";
|
||||
|
||||
const art = $("reveal-art");
|
||||
art.innerHTML = "";
|
||||
art.classList.remove("has-image");
|
||||
art.style.setProperty("--accent", game.accent || "#d9c2e8");
|
||||
art.append(el("span", "cover-fallback", game.title));
|
||||
|
||||
const coverUrl = getCoverUrl(game);
|
||||
if (coverUrl) {
|
||||
const img = document.createElement("img");
|
||||
img.className = "cover-img";
|
||||
img.alt = "";
|
||||
img.src = coverUrl;
|
||||
img.addEventListener("load", function () { art.classList.add("has-image"); });
|
||||
img.addEventListener("error", function () { img.remove(); });
|
||||
art.append(img);
|
||||
}
|
||||
|
||||
const steamLink = $("reveal-steam");
|
||||
const browserLink = $("reveal-browser");
|
||||
if (key) {
|
||||
steamLink.hidden = false;
|
||||
steamLink.href = getActivationUrl(key);
|
||||
steamLink.target = "_blank";
|
||||
steamLink.textContent = "Activeer op Steam";
|
||||
const shopUrl = game.url || (game.appId
|
||||
? "https://store.steampowered.com/app/" + game.appId + "/"
|
||||
: "");
|
||||
if (shopUrl) {
|
||||
browserLink.hidden = false;
|
||||
browserLink.href = shopUrl;
|
||||
browserLink.textContent = "of bekijk het spel in de winkel";
|
||||
} else {
|
||||
browserLink.hidden = true;
|
||||
}
|
||||
} else if (game.appId) {
|
||||
steamLink.hidden = false;
|
||||
steamLink.href = "steam://store/" + game.appId;
|
||||
steamLink.target = "_self";
|
||||
steamLink.textContent = "Open in Steam";
|
||||
browserLink.hidden = false;
|
||||
browserLink.href = "https://store.steampowered.com/app/" + game.appId + "/";
|
||||
browserLink.textContent = "of bekijk in de browser";
|
||||
} else if (game.url) {
|
||||
steamLink.hidden = false;
|
||||
steamLink.href = game.url;
|
||||
steamLink.target = "_blank";
|
||||
steamLink.textContent = review ? "Bekijk het spel" : "Open het spel";
|
||||
browserLink.hidden = true;
|
||||
} else {
|
||||
steamLink.hidden = true;
|
||||
browserLink.hidden = true;
|
||||
}
|
||||
|
||||
const continueBtn = $("reveal-continue");
|
||||
continueBtn.textContent = review ? "Sluiten" : (index === totalLevels() - 1 ? "Naar de finale" : "Verder");
|
||||
revealCallback = !review && typeof onContinue === "function" ? onContinue : null;
|
||||
revealSteamCallback = !review && typeof opts.onSteamOpen === "function" ? opts.onSteamOpen : null;
|
||||
|
||||
revealOverlay.hidden = false;
|
||||
document.body.classList.add("overlay-open");
|
||||
play(review ? "click" : "reveal");
|
||||
continueBtn.focus();
|
||||
}
|
||||
|
||||
function closeReveal(triggerCallback) {
|
||||
if (revealOverlay.hidden) return;
|
||||
revealOverlay.hidden = true;
|
||||
document.body.classList.remove("overlay-open");
|
||||
const callback = revealCallback;
|
||||
revealCallback = null;
|
||||
revealSteamCallback = null;
|
||||
if (revealLastFocus && typeof revealLastFocus.focus === "function") {
|
||||
revealLastFocus.focus();
|
||||
}
|
||||
if (triggerCallback && callback) callback();
|
||||
}
|
||||
|
||||
function showConfirm(onYes) {
|
||||
confirmLastFocus = document.activeElement;
|
||||
confirmCallback = typeof onYes === "function" ? onYes : null;
|
||||
confirmOverlay.hidden = false;
|
||||
document.body.classList.add("overlay-open");
|
||||
$("confirm-no").focus();
|
||||
}
|
||||
|
||||
function closeConfirm() {
|
||||
if (confirmOverlay.hidden) return;
|
||||
confirmOverlay.hidden = true;
|
||||
if (revealOverlay.hidden) document.body.classList.remove("overlay-open");
|
||||
confirmCallback = null;
|
||||
if (confirmLastFocus && typeof confirmLastFocus.focus === "function") {
|
||||
confirmLastFocus.focus();
|
||||
}
|
||||
}
|
||||
|
||||
function toast(message) {
|
||||
toastNode.textContent = message;
|
||||
toastNode.hidden = false;
|
||||
window.clearTimeout(toastTimer);
|
||||
toastTimer = window.setTimeout(function () {
|
||||
toastNode.hidden = true;
|
||||
}, 2400);
|
||||
}
|
||||
|
||||
function renderFinaleGifts() {
|
||||
const grid = $("finale-gifts");
|
||||
grid.innerHTML = "";
|
||||
const games = GAME_CONFIG.games || [];
|
||||
|
||||
games.forEach(function (game, index) {
|
||||
const card = el("button", "finale-card");
|
||||
card.type = "button";
|
||||
card.append(coverArt(game, "finale-art"));
|
||||
card.append(el("span", "finale-card-title", game.title));
|
||||
card.setAttribute("aria-label", "Bekijk cadeau: " + game.title);
|
||||
card.addEventListener("click", function () {
|
||||
showReveal(index, null, { review: true });
|
||||
});
|
||||
grid.append(card);
|
||||
});
|
||||
}
|
||||
|
||||
function showFinale() {
|
||||
$("finale-title").textContent = GAME_CONFIG.finaleTitle;
|
||||
$("finale-message").textContent = GAME_CONFIG.finalMessage;
|
||||
$("finale-signature").textContent = GAME_CONFIG.finaleSignature || ("Liefs, " + GAME_CONFIG.yourName);
|
||||
renderFinaleGifts();
|
||||
showScreen("finale");
|
||||
play("reveal");
|
||||
|
||||
const reduceMotion = window.matchMedia && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
||||
if (!reduceMotion) spawnConfetti();
|
||||
|
||||
const title = $("finale-title");
|
||||
title.setAttribute("tabindex", "-1");
|
||||
title.focus();
|
||||
}
|
||||
|
||||
function spawnConfetti() {
|
||||
const old = document.querySelector(".confetti-layer");
|
||||
if (old) old.remove();
|
||||
|
||||
const layer = el("div", "confetti-layer");
|
||||
layer.setAttribute("aria-hidden", "true");
|
||||
const colors = ["#f4a7b9", "#f6d98a", "#bfe3d0", "#cdbde8", "#f29b8b", "#fff7ef"];
|
||||
|
||||
for (let i = 0; i < 42; i += 1) {
|
||||
const piece = el("span", "confetti");
|
||||
piece.style.left = (Math.random() * 100).toFixed(1) + "%";
|
||||
piece.style.background = colors[i % colors.length];
|
||||
piece.style.width = (6 + Math.random() * 7).toFixed(1) + "px";
|
||||
piece.style.height = (9 + Math.random() * 9).toFixed(1) + "px";
|
||||
piece.style.animationDelay = (Math.random() * 1.8).toFixed(2) + "s";
|
||||
piece.style.animationDuration = (3.4 + Math.random() * 2.6).toFixed(2) + "s";
|
||||
piece.style.setProperty("--drift", (Math.random() * 160 - 80).toFixed(0) + "px");
|
||||
layer.append(piece);
|
||||
}
|
||||
|
||||
screens.finale.append(layer);
|
||||
window.setTimeout(function () { layer.remove(); }, 8000);
|
||||
}
|
||||
|
||||
function showConfigError(messages) {
|
||||
const banner = el("div", "config-warning");
|
||||
banner.setAttribute("role", "alert");
|
||||
banner.textContent = "Let op: " + messages.join(" ");
|
||||
const inner = document.querySelector(".welcome-inner");
|
||||
inner.insertBefore(banner, $("start-btn"));
|
||||
if (window.console && console.error) {
|
||||
console.error("Configuratieprobleem:", messages);
|
||||
}
|
||||
}
|
||||
|
||||
function init() {
|
||||
document.title = "Voor " + GAME_CONFIG.herName + " — een tuin vol cadeautjes";
|
||||
$("welcome-title").textContent = GAME_CONFIG.welcomeTitle || "Voor";
|
||||
$("welcome-name").textContent = GAME_CONFIG.herName;
|
||||
$("welcome-text").textContent = GAME_CONFIG.welcomeText;
|
||||
$("finale-title").textContent = GAME_CONFIG.finaleTitle;
|
||||
$("finale-message").textContent = GAME_CONFIG.finalMessage;
|
||||
$("finale-signature").textContent = GAME_CONFIG.finaleSignature || ("Liefs, " + GAME_CONFIG.yourName);
|
||||
updateMuteButton();
|
||||
|
||||
$("start-btn").addEventListener("click", function () { App.goToMap(); });
|
||||
homeBtn.addEventListener("click", function () { App.goHome(); });
|
||||
muteBtn.addEventListener("click", toggleMute);
|
||||
$("reset-btn").addEventListener("click", function () {
|
||||
showConfirm(function () { App.resetGame(); });
|
||||
});
|
||||
$("finale-btn").addEventListener("click", showFinale);
|
||||
$("finale-back").addEventListener("click", function () { App.goToMap(); });
|
||||
|
||||
$("reveal-continue").addEventListener("click", function () { closeReveal(true); });
|
||||
$("reveal-key-copy").addEventListener("click", copyKey);
|
||||
$("reveal-key-value").addEventListener("focus", function () { this.select(); });
|
||||
[$("reveal-steam"), $("reveal-browser")].forEach(function (link) {
|
||||
link.addEventListener("click", function () {
|
||||
if (revealSteamCallback) revealSteamCallback();
|
||||
});
|
||||
});
|
||||
$("confirm-no").addEventListener("click", closeConfirm);
|
||||
$("confirm-yes").addEventListener("click", function () {
|
||||
const callback = confirmCallback;
|
||||
closeConfirm();
|
||||
if (callback) callback();
|
||||
});
|
||||
|
||||
document.addEventListener("keydown", function (event) {
|
||||
if (event.key !== "Escape") return;
|
||||
if (!confirmOverlay.hidden) {
|
||||
closeConfirm();
|
||||
return;
|
||||
}
|
||||
if (!revealOverlay.hidden) {
|
||||
closeReveal(true);
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener("pointerdown", function () {
|
||||
ensureAudio();
|
||||
}, { once: true });
|
||||
|
||||
updateProgress();
|
||||
}
|
||||
|
||||
return {
|
||||
init: init,
|
||||
play: play,
|
||||
setState: setState,
|
||||
renderMap: renderMap,
|
||||
showScreen: showScreen,
|
||||
showLevel: showLevel,
|
||||
setHint: setHint,
|
||||
showReveal: showReveal,
|
||||
showFinale: showFinale,
|
||||
showConfigError: showConfigError,
|
||||
toast: toast,
|
||||
getScreen: function () { return currentScreen; }
|
||||
};
|
||||
})();
|
||||
Reference in new issue
Block a user