tarinai/js/main.js

145 lines
4.8 KiB
JavaScript
Raw Normal View History

2026-06-18 18:59:56 +09:00
"use strict";
let last = nowSec();
let statsTimer = 0;
let fpsTimer = 0;
let fpsFrames = 0;
2026-06-19 14:00:48 +09:00
let perfResizeTimer = 0;
let lastPerfLevel = 0;
2026-06-24 17:39:44 +09:00
let lastPerfMaxDpr = 0;
2026-06-18 18:59:56 +09:00
window.__tarinaiFps = 0;
2026-06-20 23:27:39 +09:00
2026-06-21 14:09:35 +09:00
const LOADING_SPRITES = [
"assets/sprites/tarinai_01_smile.webp",
"assets/sprites/tarinai_02_angry.webp",
"assets/sprites/tarinai_03_teary.webp",
"assets/sprites/tarinai_04_jito.webp",
"assets/sprites/tarinai_05_drool.webp",
"assets/sprites/tarinai_06_cry.webp",
"assets/sprites/tarinai_07_sleep.webp",
"assets/sprites/tarinai_08_pokan.webp",
"assets/sprites/tarinai_11_weak.webp",
"assets/sprites/tarinai_21_normal_happy.webp",
2026-06-21 22:29:00 +09:00
"assets/sprites/tarinai_29_hungry_70.webp",
2026-06-21 14:09:35 +09:00
];
let loadingSpriteTimer = 0;
function shuffledLoadingSprites() {
const list = [...LOADING_SPRITES];
for (let i = list.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[list[i], list[j]] = [list[j], list[i]];
}
return list.slice(0, 4);
}
function renderLoadingSprites() {
const strip = document.getElementById("loadingSpriteStrip");
if (!strip) return;
strip.innerHTML = "";
const frag = document.createDocumentFragment();
for (const src of shuffledLoadingSprites()) {
const card = document.createElement("div");
card.className = "loading-sprite-card";
const img = document.createElement("img");
img.src = src;
img.alt = "";
img.loading = "eager";
card.appendChild(img);
frag.appendChild(card);
}
strip.appendChild(frag);
}
function initLoadingShowcase() {
renderLoadingSprites();
if (loadingSpriteTimer) clearInterval(loadingSpriteTimer);
loadingSpriteTimer = window.setInterval(renderLoadingSprites, 1200);
}
2026-06-20 23:27:39 +09:00
function setLoadingProgress(text = "", ratio = 0) {
const screen = document.getElementById("loadingScreen");
if (!screen) return;
const pct = clamp(Number(ratio) || 0, 0, 1);
const label = document.getElementById("loadingText");
const bar = document.getElementById("loadingBar");
const percent = document.getElementById("loadingPercent");
if (label && text) label.textContent = text;
if (bar) bar.style.width = `${Math.round(pct * 100)}%`;
if (percent) percent.textContent = `${Math.round(pct * 100)}%`;
}
function hideLoadingScreen() {
2026-06-21 14:09:35 +09:00
if (loadingSpriteTimer) { clearInterval(loadingSpriteTimer); loadingSpriteTimer = 0; }
2026-06-20 23:27:39 +09:00
setLoadingProgress("\u8d77\u52d5\u5b8c\u4e86", 1);
const screen = document.getElementById("loadingScreen");
if (!screen) return;
window.setTimeout(() => screen.classList.add("hidden"), 120);
}
2026-06-18 18:59:56 +09:00
function loop() {
const t = nowSec();
const rawDt = t - last;
const dt = clamp(rawDt, 0, 0.05);
last = t;
fpsTimer += rawDt;
fpsFrames += 1;
if (fpsTimer >= 0.5) {
window.__tarinaiFps = Math.round(fpsFrames / Math.max(fpsTimer, 0.001));
2026-06-21 14:09:35 +09:00
window.TarinaiPerformance?.updateFps?.(window.__tarinaiFps, world);
2026-06-18 18:59:56 +09:00
fpsTimer = 0;
fpsFrames = 0;
}
world.update(dt);
render();
statsTimer += dt;
2026-06-24 17:39:44 +09:00
const quality = world.performanceQuality?.() || {};
const perf = Number(quality.level ?? (world.performanceLevel ? world.performanceLevel() : 0)) || 0;
2026-06-19 14:00:48 +09:00
perfResizeTimer += rawDt;
if (perfResizeTimer > 1.5) {
2026-06-24 17:39:44 +09:00
const maxDpr = Number(quality.maxDpr || 0) || 0;
if (perf !== lastPerfLevel || Math.abs(maxDpr - lastPerfMaxDpr) > 0.08) {
2026-06-19 14:00:48 +09:00
lastPerfLevel = perf;
2026-06-24 17:39:44 +09:00
lastPerfMaxDpr = maxDpr;
2026-06-19 14:00:48 +09:00
resizeCanvas();
}
perfResizeTimer = 0;
}
2026-06-21 14:09:35 +09:00
const statsInterval = world.performanceQuality?.().statsInterval ?? (perf >= 3 ? 1.20 : perf === 2 ? 0.92 : perf === 1 ? 0.68 : 0.48);
2026-06-19 02:27:19 +09:00
if (statsTimer > statsInterval) {
2026-06-18 18:59:56 +09:00
renderStats();
statsTimer = 0;
}
requestAnimationFrame(loop);
}
2026-06-21 14:09:35 +09:00
initLoadingShowcase();
2026-06-20 23:27:39 +09:00
setLoadingProgress("\u521d\u671f\u753b\u50cf\u3092\u8aad\u307f\u8fbc\u307f\u4e2d", 0.08);
loadImages(null, (done, total) => {
const p = total > 0 ? done / total : 1;
setLoadingProgress(`\u521d\u671f\u753b\u50cf\u3092\u8aad\u307f\u8fbc\u307f\u4e2d ${done}/${total}`, 0.08 + p * 0.46);
}).then(() => {
setLoadingProgress("UI\u3092\u6e96\u5099\u4e2d", 0.62);
2026-06-18 18:59:56 +09:00
bindUI();
2026-06-20 23:27:39 +09:00
setLoadingProgress("\u30d5\u30a3\u30fc\u30eb\u30c9\u3092\u69cb\u7bc9\u4e2d", 0.72);
2026-06-19 14:00:48 +09:00
applyFieldLayout("garden");
world.reset(null, "garden");
2026-06-18 18:59:56 +09:00
selectTool("observe");
2026-06-20 23:27:39 +09:00
setLoadingProgress("\u8868\u793a\u3092\u521d\u671f\u5316\u4e2d", 0.84);
2026-06-18 18:59:56 +09:00
renderLog(world.logs);
renderArchive();
render();
renderStats();
syncTopButtons();
2026-06-19 23:22:15 +09:00
if (typeof startBackgroundImageLoading === "function") startBackgroundImageLoading();
2026-06-20 23:27:39 +09:00
setLoadingProgress("\u30b7\u30df\u30e5\u30ec\u30fc\u30b7\u30e7\u30f3\u3092\u958b\u59cb\u4e2d", 0.94);
2026-06-18 18:59:56 +09:00
loop();
2026-06-20 23:27:39 +09:00
requestAnimationFrame(hideLoadingScreen);
2026-06-18 18:59:56 +09:00
});
2026-06-21 14:09:35 +09:00
if ("serviceWorker" in navigator) {
window.addEventListener("load", () => {
2026-06-22 02:03:19 +09:00
const swUrl = window.TARINAI_APP?.withVersion?.("./service-worker.js") || "./service-worker.js?v=15.20.16";
2026-06-21 14:09:35 +09:00
navigator.serviceWorker.register(swUrl, { updateViaCache: "none" }).catch(() => undefined);
});
}