Files
Physilinks/ui.js
2025-12-12 22:21:46 +01:00

157 lines
4.7 KiB
JavaScript

(() => {
const create = () => {
const sceneEl = document.getElementById("scene-wrapper");
const activeColorEl = document.getElementById("active-color");
const chainLenEl = document.getElementById("chain-length");
const spawnRateEl = document.getElementById("spawn-rate");
const minLinkEl = document.getElementById("min-link");
const paletteLegendEl = document.getElementById("palette-legend");
const scoreEl = document.getElementById("score");
const highScoreEl = document.getElementById("high-score");
const sceneSelectEl = document.getElementById("scene-select");
const gameOverEl = document.getElementById("game-over");
const finalScoreEl = document.getElementById("final-score");
const restartBtn = document.getElementById("restart-btn");
const pauseBtn = document.getElementById("pause-btn");
const pauseOverlay = document.getElementById("pause-overlay");
const handlers = {
onPauseToggle: null,
onRestart: null,
onSceneChange: null,
};
if (pauseBtn) {
pauseBtn.addEventListener("click", () => {
if (handlers.onPauseToggle) handlers.onPauseToggle();
});
}
if (restartBtn) {
restartBtn.addEventListener("click", () => {
if (handlers.onRestart) handlers.onRestart();
});
}
if (sceneSelectEl) {
sceneSelectEl.addEventListener("change", (e) => {
if (handlers.onSceneChange) handlers.onSceneChange(e.target.value);
});
}
window.addEventListener("keydown", (e) => {
if (e.key === "Escape" && handlers.onPauseToggle) {
handlers.onPauseToggle();
}
});
const setHandlers = (nextHandlers = {}) => {
Object.assign(handlers, nextHandlers);
};
const setSceneOptions = (scenes, activeId) => {
if (!sceneSelectEl) return;
sceneSelectEl.innerHTML = "";
scenes.forEach((scene) => {
const opt = document.createElement("option");
opt.value = scene.id;
opt.textContent = scene.name;
sceneSelectEl.appendChild(opt);
});
if (activeId) {
sceneSelectEl.value = activeId;
}
};
const setSceneSelection = (sceneId) => {
if (sceneSelectEl) {
sceneSelectEl.value = sceneId;
}
};
const setPauseState = (paused) => {
if (pauseOverlay) {
pauseOverlay.classList.toggle("visible", paused);
}
if (pauseBtn) {
pauseBtn.textContent = paused ? "Resume" : "Pause";
}
};
const showGameOver = (score) => {
if (finalScoreEl) finalScoreEl.textContent = score;
if (gameOverEl) gameOverEl.classList.add("visible");
};
const hideGameOver = () => {
if (gameOverEl) gameOverEl.classList.remove("visible");
};
const spawnScorePopup = (point, amount, color) => {
if (!point || !sceneEl) return;
const el = document.createElement("div");
el.className = "floating-score";
el.textContent = `+${amount}`;
el.style.left = `${point.x}px`;
el.style.top = `${point.y}px`;
el.style.color = color || "#e0f2fe";
sceneEl.appendChild(el);
setTimeout(() => el.remove(), 950);
};
const updateHud = ({
spawnIntervalMs,
minChain,
chainLength,
score,
highScore,
activeColor,
}) => {
if (spawnRateEl) spawnRateEl.textContent = `${spawnIntervalMs} ms`;
if (minLinkEl) minLinkEl.textContent = minChain;
if (chainLenEl) chainLenEl.textContent = chainLength;
if (scoreEl) scoreEl.textContent = score;
if (highScoreEl) highScoreEl.textContent = highScore;
if (activeColorEl) {
if (activeColor) {
activeColorEl.textContent = "";
activeColorEl.style.display = "inline-block";
activeColorEl.style.width = "14px";
activeColorEl.style.height = "14px";
activeColorEl.style.borderRadius = "50%";
activeColorEl.style.background = activeColor;
activeColorEl.style.border = "1px solid rgba(255,255,255,0.3)";
} else {
activeColorEl.removeAttribute("style");
activeColorEl.textContent = "—";
}
}
};
const buildLegend = (palette) => {
if (!paletteLegendEl) return;
paletteLegendEl.innerHTML = "";
palette.forEach((color) => {
const swatch = document.createElement("span");
swatch.style.background = color;
paletteLegendEl.appendChild(swatch);
});
};
return {
sceneEl,
updateHud,
buildLegend,
spawnScorePopup,
setPauseState,
showGameOver,
hideGameOver,
setSceneOptions,
setSceneSelection,
setHandlers,
};
};
window.PhysilinksUI = { create };
})();