diff mrjunejune/src/public/dog-game.js @ 240:c345083cd8a7

[mrjunejune] Show star animation in light mode
author MrJuneJune <me@mrjunejune.com>
date Mon, 03 Aug 2026 10:48:59 -0700
parents 84826b3c655b
children 9c2eec61a152
line wrap: on
line diff
--- a/mrjunejune/src/public/dog-game.js	Mon Aug 03 10:36:12 2026 -0700
+++ b/mrjunejune/src/public/dog-game.js	Mon Aug 03 10:48:59 2026 -0700
@@ -20,18 +20,52 @@
 treatImage.src = "/public/dog-treat.png";
 
 // Load star images for background
+const lightStarColors = ["#315a91", "#8f3f63", "#34705f", "#76519b"];
 let starImages = [
-  { src: "/public/start-large.png", img: new Image() },
-  { src: "/public/start-small-1.png", img: new Image() },
-  { src: "/public/start-small-2.png", img: new Image() },
-  { src: "/public/start-small-3.png", img: new Image() }
+  { src: "/public/start-large.png", img: new Image(), lightImg: null },
+  { src: "/public/start-small-1.png", img: new Image(), lightImg: null },
+  { src: "/public/start-small-2.png", img: new Image(), lightImg: null },
+  { src: "/public/start-small-3.png", img: new Image(), lightImg: null }
 ];
-starImages.forEach(star => star.img.src = star.src);
+starImages.forEach((star, index) => {
+  star.img.onload = () => {
+    const tinted = document.createElement("canvas");
+    tinted.width = star.img.naturalWidth;
+    tinted.height = star.img.naturalHeight;
+    const tintedCtx = tinted.getContext("2d");
+    tintedCtx.drawImage(star.img, 0, 0);
+    tintedCtx.globalCompositeOperation = "source-in";
+    tintedCtx.fillStyle = lightStarColors[index];
+    tintedCtx.fillRect(0, 0, tinted.width, tinted.height);
+    star.lightImg = tinted;
+    updateStarPalette();
+  };
+  star.img.src = star.src;
+});
 
 const background = document.getElementById('background');
 const bgCtx = background.getContext("2d");
 const ctx = game.getContext("2d");
 const uiCtx = gameUI.getContext("2d");
+const darkModePreference = window.matchMedia("(prefers-color-scheme: dark)");
+
+function isDarkMode() {
+  const root = document.documentElement;
+  if (root.classList.contains("dark")) return true;
+  if (root.classList.contains("light-mode")) return false;
+  return darkModePreference.matches;
+}
+
+function starImageForTheme(imageIndex) {
+  const star = starImages[imageIndex];
+  return isDarkMode() ? star.img : star.lightImg || star.img;
+}
+
+function updateStarPalette() {
+  stars.forEach(star => {
+    star.image = starImageForTheme(star.imageIndex);
+  });
+}
 
 
 // Dog initial position and movement
@@ -66,7 +100,8 @@
   const starCount = window.innerWidth * 0.05;
 
   for (let i = 0; i < starCount; i++) {
-    const starType = starImages[Math.floor(Math.random() * starImages.length)];
+    const imageIndex = Math.floor(Math.random() * starImages.length);
+    const starType = starImages[imageIndex];
     const scale = 0.5 + Math.random() * 0.8; // Random scale
 
     stars.push({
@@ -76,7 +111,8 @@
       vy: (Math.random() - 0.5) * 0.5,
       rotation: Math.random() * Math.PI * 2,
       rotationSpeed: (Math.random() - 0.5) * 0.02,
-      image: starType.img,
+      imageIndex: imageIndex,
+      image: starImageForTheme(imageIndex),
       size: starType.img.width,
       scale: scale,
       opacity: 0.3 + Math.random() * 0.4 // Random opacity
@@ -286,10 +322,14 @@
 }
 resizeCanvas();
 window.addEventListener('resize', resizeCanvas);
+new MutationObserver(updateStarPalette).observe(
+  document.documentElement,
+  { attributes: true, attributeFilter: ["class"] }
+);
+darkModePreference.addEventListener("change", updateStarPalette);
 
 window.onload = () => {
   resizeCanvas();     // ensure canvas has real size
   createStars();      // stars need correct canvas size
   animateBackground(); // safe to start background animation
 };
-