From f38f6850c35cb440c9f39636fb27cbecfa69ff52 Mon Sep 17 00:00:00 2001 From: tomt610 Date: Tue, 13 Jan 2026 20:26:55 +0000 Subject: [PATCH] Add sunrise/sunset effects and improve sun positioning - Add sunrise (dawn 5-7 AM) with warm gradient, horizon glow, fading stars - Add sunset (dusk 18-20) with orange gradient, horizon glow, emerging stars - Widen sun arc from 5-85% to 3-92% for more dramatic sunset positioning - Lower horizon position for setting/rising sun (35% to 40%) - Fix mobile viewport with dvh/vw units for all overlay elements - Reduce overlay opacity for subtler atmospheric effect --- src/systems/ui/weatherEffects.js | 146 +++++++++++++++++++- style.css | 226 +++++++++++++++++++++++++++++++ 2 files changed, 365 insertions(+), 7 deletions(-) diff --git a/src/systems/ui/weatherEffects.js b/src/systems/ui/weatherEffects.js index 727f8cb..6620321 100644 --- a/src/systems/ui/weatherEffects.js +++ b/src/systems/ui/weatherEffects.js @@ -237,9 +237,9 @@ function createMist() { * Returns { left: vw%, top: dvh% } */ function calculateSunPosition(hour) { - // Daytime is roughly 6 AM to 8 PM (6-20) + // Daytime is roughly 5 AM to 8 PM (5-20) // Map hour to position along an arc - // 6 AM = far left, low | 12 PM = center, high | 6 PM = far right, low + // 5 AM = far left, low | 12 PM = center, high | 8 PM = far right, low if (hour === null) hour = 12; // Default to noon if unknown @@ -249,14 +249,14 @@ function calculateSunPosition(hour) { // Normalize to 0-1 range (5 AM = 0, 20 PM = 1) const progress = (clampedHour - 5) / 15; - // Horizontal position: 5% to 85% (left to right) - const left = 5 + progress * 80; + // Horizontal position: 3% to 92% (left to right, wider range) + const left = 3 + progress * 89; // Vertical position: parabolic arc (high at noon, low at dawn/dusk) // At progress 0.5 (noon), top should be ~8% (high) - // At progress 0 or 1, top should be ~35% (low, near horizon) + // At progress 0 or 1, top should be ~40% (low, near horizon) const normalizedProgress = (progress - 0.5) * 2; // -1 to 1 - const top = 8 + 27 * (normalizedProgress * normalizedProgress); + const top = 8 + 32 * (normalizedProgress * normalizedProgress); return { left, top }; } @@ -327,6 +327,134 @@ function createSunshine(hour) { return container; } +/** + * Create sunrise effect (dawn - warm orange/pink sky gradient with low sun) + */ +function createSunrise(hour) { + const container = document.createElement('div'); + container.className = 'rpg-weather-particles rpg-sunrise-weather'; + + // Create sunrise gradient overlay + const sunriseOverlay = document.createElement('div'); + sunriseOverlay.className = 'rpg-weather-particle rpg-sunrise-overlay'; + container.appendChild(sunriseOverlay); + + // Calculate sun position (rising from left horizon) + const sunPos = calculateSunPosition(hour); + + // Create the rising sun + const sun = document.createElement('div'); + sun.className = 'rpg-weather-particle rpg-clear-sun rpg-sunrise-sun'; + sun.style.left = `${sunPos.left}vw`; + sun.style.top = `${sunPos.top}dvh`; + container.appendChild(sun); + + // Create sun glow (more orange during sunrise) + const sunGlow = document.createElement('div'); + sunGlow.className = 'rpg-weather-particle rpg-clear-sun-glow rpg-sunrise-glow'; + sunGlow.style.left = `${sunPos.left}vw`; + sunGlow.style.top = `${sunPos.top}dvh`; + container.appendChild(sunGlow); + + // Create horizon glow + const horizonGlow = document.createElement('div'); + horizonGlow.className = 'rpg-weather-particle rpg-sunrise-horizon-glow'; + container.appendChild(horizonGlow); + + // Add some fading stars (still visible at dawn) + for (let i = 0; i < 15; i++) { + const star = document.createElement('div'); + star.className = 'rpg-weather-particle rpg-night-star rpg-sunrise-fading-star'; + star.style.left = `${Math.random() * 100}vw`; + star.style.top = `${Math.random() * 40}dvh`; + star.style.animationDelay = `${Math.random() * 3}s`; + const size = 1 + Math.random() * 1.5; + star.style.width = `${size}px`; + star.style.height = `${size}px`; + container.appendChild(star); + } + + // Add some golden dust motes + for (let i = 0; i < 12; i++) { + const particle = document.createElement('div'); + particle.className = 'rpg-weather-particle rpg-clear-dust-mote'; + particle.style.left = `${Math.random() * 100}vw`; + particle.style.top = `${Math.random() * 100}dvh`; + particle.style.animationDelay = `${Math.random() * 15}s`; + particle.style.animationDuration = `${12 + Math.random() * 8}s`; + const size = 2 + Math.random() * 3; + particle.style.width = `${size}px`; + particle.style.height = `${size}px`; + container.appendChild(particle); + } + + return container; +} + +/** + * Create sunset effect (dusk - warm red/purple sky gradient with low sun) + */ +function createSunset(hour) { + const container = document.createElement('div'); + container.className = 'rpg-weather-particles rpg-sunset-weather'; + + // Create sunset gradient overlay + const sunsetOverlay = document.createElement('div'); + sunsetOverlay.className = 'rpg-weather-particle rpg-sunset-overlay'; + container.appendChild(sunsetOverlay); + + // Calculate sun position (setting on right horizon) + const sunPos = calculateSunPosition(hour); + + // Create the setting sun + const sun = document.createElement('div'); + sun.className = 'rpg-weather-particle rpg-clear-sun rpg-sunset-sun'; + sun.style.left = `${sunPos.left}vw`; + sun.style.top = `${sunPos.top}dvh`; + container.appendChild(sun); + + // Create sun glow (more red during sunset) + const sunGlow = document.createElement('div'); + sunGlow.className = 'rpg-weather-particle rpg-clear-sun-glow rpg-sunset-glow'; + sunGlow.style.left = `${sunPos.left}vw`; + sunGlow.style.top = `${sunPos.top}dvh`; + container.appendChild(sunGlow); + + // Create horizon glow + const horizonGlow = document.createElement('div'); + horizonGlow.className = 'rpg-weather-particle rpg-sunset-horizon-glow'; + container.appendChild(horizonGlow); + + // Add some early stars (appearing at dusk) + for (let i = 0; i < 20; i++) { + const star = document.createElement('div'); + star.className = 'rpg-weather-particle rpg-night-star rpg-sunset-emerging-star'; + star.style.left = `${Math.random() * 100}vw`; + star.style.top = `${Math.random() * 50}dvh`; + star.style.animationDelay = `${Math.random() * 5}s`; + const size = 1 + Math.random() * 1.5; + star.style.width = `${size}px`; + star.style.height = `${size}px`; + container.appendChild(star); + } + + // Add some golden/pink dust motes + for (let i = 0; i < 12; i++) { + const particle = document.createElement('div'); + particle.className = 'rpg-weather-particle rpg-clear-dust-mote rpg-sunset-dust'; + particle.style.left = `${Math.random() * 100}vw`; + particle.style.top = `${Math.random() * 100}dvh`; + particle.style.animationDelay = `${Math.random() * 15}s`; + particle.style.animationDuration = `${12 + Math.random() * 8}s`; + const size = 2 + Math.random() * 3; + particle.style.width = `${size}px`; + particle.style.height = `${size}px`; + container.appendChild(particle); + } + + return container; +} + /** * Create clear nighttime weather effect with moon, stars, and fireflies */ @@ -572,9 +700,13 @@ export function updateWeatherEffect() { weatherContainer = createMist(); break; case 'sunny': - // Use nighttime effect for clear weather at night + // Use appropriate effect based on time of day if (timeOfDay === 'night') { weatherContainer = createNighttime(hour); + } else if (timeOfDay === 'dawn') { + weatherContainer = createSunrise(hour); + } else if (timeOfDay === 'dusk') { + weatherContainer = createSunset(hour); } else { weatherContainer = createSunshine(hour); } diff --git a/style.css b/style.css index 596438b..88d9a70 100644 --- a/style.css +++ b/style.css @@ -9806,6 +9806,200 @@ body[data-theme="cyberpunk"] .rpg-music-widget-play { } } +/* ===== Sunrise Effects (Dawn) ===== */ + +.rpg-sunrise-weather { + overflow: hidden; +} + +/* Sunrise sky gradient overlay */ +.rpg-sunrise-overlay { + position: fixed; + top: 0; + left: 0; + width: 100vw; + height: 100dvh; + background: linear-gradient(to bottom, + rgba(40, 30, 80, 0.1) 0%, + rgba(120, 60, 120, 0.08) 15%, + rgba(200, 100, 100, 0.1) 35%, + rgba(255, 140, 100, 0.12) 55%, + rgba(255, 180, 120, 0.1) 75%, + rgba(255, 200, 150, 0.08) 100%); + animation: rpg-sunrise-sky-transition 30s ease-in-out infinite alternate; + pointer-events: none; +} + +@keyframes rpg-sunrise-sky-transition { + 0% { + opacity: 0.8; + } + 100% { + opacity: 1; + } +} + +/* Sunrise sun - more orange/red */ +.rpg-sunrise-sun { + background: radial-gradient(circle at 40% 40%, + rgba(255, 255, 220, 1) 0%, + rgba(255, 220, 150, 1) 30%, + rgba(255, 160, 80, 0.9) 60%, + rgba(255, 100, 50, 0.6) 80%, + rgba(255, 80, 30, 0) 100%) !important; + box-shadow: + 0 0 40px 15px rgba(255, 180, 100, 0.6), + 0 0 80px 30px rgba(255, 140, 80, 0.4), + 0 0 120px 50px rgba(255, 100, 50, 0.2) !important; +} + +/* Sunrise sun glow - warm orange */ +.rpg-sunrise-glow { + background: radial-gradient(circle at center, + rgba(255, 200, 150, 0.35) 0%, + rgba(255, 160, 100, 0.2) 30%, + rgba(255, 120, 80, 0.1) 50%, + transparent 70%) !important; +} + +/* Horizon glow for sunrise */ +.rpg-sunrise-horizon-glow { + position: fixed; + bottom: 0; + left: 0; + width: 100vw; + height: 40dvh; + background: linear-gradient(to top, + rgba(255, 160, 100, 0.15) 0%, + rgba(255, 140, 90, 0.1) 20%, + rgba(255, 120, 80, 0.05) 50%, + rgba(255, 100, 70, 0.02) 75%, + transparent 100%); + animation: rpg-horizon-glow-pulse 8s ease-in-out infinite; + pointer-events: none; +} + +@keyframes rpg-horizon-glow-pulse { + 0%, 100% { + opacity: 0.7; + } + 50% { + opacity: 1; + } +} + +/* Fading stars at sunrise */ +.rpg-sunrise-fading-star { + opacity: 0.3 !important; + animation: rpg-star-fade-out 4s ease-in-out infinite !important; +} + +@keyframes rpg-star-fade-out { + 0%, 100% { + opacity: 0.2; + } + 50% { + opacity: 0.4; + } +} + +/* ===== Sunset Effects (Dusk) ===== */ + +.rpg-sunset-weather { + overflow: hidden; +} + +/* Sunset sky gradient overlay */ +.rpg-sunset-overlay { + position: fixed; + top: 0; + left: 0; + width: 100vw; + height: 100dvh; + background: linear-gradient(to bottom, + rgba(30, 20, 60, 0.12) 0%, + rgba(80, 40, 100, 0.1) 15%, + rgba(150, 60, 90, 0.12) 30%, + rgba(220, 80, 70, 0.12) 50%, + rgba(255, 120, 80, 0.12) 70%, + rgba(255, 160, 100, 0.1) 85%, + rgba(255, 180, 120, 0.06) 100%); + animation: rpg-sunset-sky-transition 30s ease-in-out infinite alternate; + pointer-events: none; +} + +@keyframes rpg-sunset-sky-transition { + 0% { + opacity: 1; + } + 100% { + opacity: 0.8; + } +} + +/* Sunset sun - more red/deep orange */ +.rpg-sunset-sun { + background: radial-gradient(circle at 40% 40%, + rgba(255, 240, 200, 1) 0%, + rgba(255, 180, 100, 1) 30%, + rgba(255, 120, 60, 0.9) 60%, + rgba(255, 80, 40, 0.6) 80%, + rgba(200, 50, 30, 0) 100%) !important; + box-shadow: + 0 0 40px 15px rgba(255, 140, 80, 0.6), + 0 0 80px 30px rgba(255, 100, 60, 0.4), + 0 0 120px 50px rgba(200, 60, 40, 0.2) !important; +} + +/* Sunset sun glow - deep orange/red */ +.rpg-sunset-glow { + background: radial-gradient(circle at center, + rgba(255, 160, 120, 0.35) 0%, + rgba(255, 120, 80, 0.2) 30%, + rgba(200, 80, 60, 0.1) 50%, + transparent 70%) !important; +} + +/* Horizon glow for sunset */ +.rpg-sunset-horizon-glow { + position: fixed; + bottom: 0; + left: 0; + width: 100vw; + height: 45dvh; + background: linear-gradient(to top, + rgba(255, 120, 60, 0.18) 0%, + rgba(255, 100, 50, 0.12) 20%, + rgba(220, 70, 50, 0.06) 45%, + rgba(150, 50, 60, 0.02) 70%, + transparent 100%); + animation: rpg-horizon-glow-pulse 8s ease-in-out infinite; + pointer-events: none; +} + +/* Emerging stars at sunset */ +.rpg-sunset-emerging-star { + animation: rpg-star-emerge 5s ease-in-out infinite !important; +} + +@keyframes rpg-star-emerge { + 0%, 100% { + opacity: 0.3; + } + 50% { + opacity: 0.7; + } +} + +/* Sunset dust motes - pinkish tint */ +.rpg-sunset-dust { + background: radial-gradient(circle at 30% 30%, + rgba(255, 200, 180, 0.9) 0%, + rgba(255, 180, 160, 0.6) 50%, + rgba(255, 160, 140, 0) 100%) !important; + box-shadow: 0 0 6px 2px rgba(255, 180, 160, 0.4) !important; +} + /* Lens flare effect */ .rpg-clear-lens-flare { position: fixed; @@ -10180,6 +10374,12 @@ body[data-theme="cyberpunk"] .rpg-music-widget-play { .rpg-night-shooting-star { animation-duration: 18s; } + + /* Sunrise/Sunset mobile optimizations */ + .rpg-sunrise-horizon-glow, + .rpg-sunset-horizon-glow { + height: 35%; + } } /* Foreground mode - reduced opacity for celestial bodies to not obstruct content */ @@ -10227,6 +10427,32 @@ body[data-theme="cyberpunk"] .rpg-music-widget-play { opacity: 0.6; } +/* Sunrise/Sunset foreground mode */ +.rpg-weather-foreground .rpg-sunrise-overlay, +.rpg-weather-foreground .rpg-sunset-overlay { + opacity: 0.4; +} + +.rpg-weather-foreground .rpg-sunrise-horizon-glow, +.rpg-weather-foreground .rpg-sunset-horizon-glow { + opacity: 0.3; +} + +.rpg-weather-foreground .rpg-sunrise-sun, +.rpg-weather-foreground .rpg-sunset-sun { + opacity: 0.5 !important; +} + +.rpg-weather-foreground .rpg-sunrise-glow, +.rpg-weather-foreground .rpg-sunset-glow { + opacity: 0.3 !important; +} + +.rpg-weather-foreground .rpg-sunrise-fading-star, +.rpg-weather-foreground .rpg-sunset-emerging-star { + opacity: 0.2 !important; +} + /* Lightning flash effect */ .rpg-lightning { position: fixed;