diff --git a/index.html b/index.html index f0194d2..0fd6071 100644 --- a/index.html +++ b/index.html @@ -4,7 +4,7 @@ - + diff --git a/package.json b/package.json index 624f041..43e16ab 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "amerc-site", - "version": "0.59.0-a11y", + "version": "0.60.0-canvasperf", "private": true, "type": "module", "scripts": { diff --git a/src/Scene2D.jsx b/src/Scene2D.jsx index c8b40cf..dfbf13d 100644 --- a/src/Scene2D.jsx +++ b/src/Scene2D.jsx @@ -7,7 +7,7 @@ import Account from './Account.jsx'; import TavernGame from './TavernGame.jsx'; import { api } from './api.js'; -const RELEASE = '0.59.0-a11y'; +const RELEASE = '0.60.0-canvasperf'; const NAV = [ { id: 'home', label: 'Tavern' }, diff --git a/src/TavernGame.jsx b/src/TavernGame.jsx index c5888d5..a7a4832 100644 --- a/src/TavernGame.jsx +++ b/src/TavernGame.jsx @@ -57,12 +57,13 @@ export default function TavernGame({ onHotspot, stats }) { useEffect(() => { statsRef.current = stats; }, [stats]); const [ready, setReady] = useState(false); useEffect(() => { - const keys = Object.keys(SRC); const S = {}; let loaded = 0, raf, f = 0, buf; + const keys = Object.keys(SRC); const S = {}; let loaded = 0, raf, f = 0, buf, paused = false, io; const start = () => { setReady(true); buf = document.createElement('canvas'); buf.width = W; buf.height = H; buildStatic(buf, S); const ctx = canvasRef.current.getContext('2d'); ctx.imageSmoothingEnabled = false; const render = () => { + if (paused) return; f++; ctx.drawImage(buf, 0, 0); // bartender (a clothed guard tending bar) behind the bar (idle bob) @@ -107,9 +108,15 @@ export default function TavernGame({ onHotspot, stats }) { raf = requestAnimationFrame(render); }; render(); + // pause the 60fps loop while the tavern is scrolled out of view (CPU/battery) + io = new IntersectionObserver(([e]) => { + if (e.isIntersecting) { if (paused) { paused = false; render(); } } + else if (!paused) { paused = true; cancelAnimationFrame(raf); } + }, { threshold: 0 }); + io.observe(canvasRef.current); }; keys.forEach((k) => { const im = new Image(); im.onload = () => { if (++loaded === keys.length) start(); }; im.src = SRC[k]; S[k] = im; }); - return () => cancelAnimationFrame(raf); + return () => { cancelAnimationFrame(raf); if (io) io.disconnect(); }; }, []); return (