From 857d56a878f97aeef61df75d18a3531de889e815 Mon Sep 17 00:00:00 2001 From: Dennis Postma Date: Sat, 7 Dec 2024 22:50:27 +0100 Subject: [PATCH] Overriding zone effects now works --- src/components/Effects.vue | 235 ++++++++++++++----------------------- 1 file changed, 90 insertions(+), 145 deletions(-) diff --git a/src/components/Effects.vue b/src/components/Effects.vue index a6a6f7c..d0468fc 100644 --- a/src/components/Effects.vue +++ b/src/components/Effects.vue @@ -10,24 +10,26 @@ import { onBeforeUnmount, onMounted, ref, watch } from 'vue' import type { WeatherState } from '@/types' // Constants -const SUNRISE_HOUR = 6 -const SUNSET_HOUR = 20 -const DAY_STRENGTH = 100 -const NIGHT_STRENGTH = 30 +const LIGHT_CONFIG = { + SUNRISE_HOUR: 6, + SUNSET_HOUR: 20, + DAY_STRENGTH: 100, + NIGHT_STRENGTH: 30 +} -// Stores +// Stores and refs const gameStore = useGameStore() const zoneStore = useZoneStore() - -// Scene ref const sceneRef = ref(null) -// Effect refs -const lightEffect = ref(null) -const rainEmitter = ref(null) -const fogSprite = ref(null) +// Effect objects +const effects = { + light: ref(null), + rain: ref(null), + fog: ref(null) +} -// State refs +// Weather state const weatherState = ref({ isRainEnabled: false, rainPercentage: 0, @@ -35,36 +37,24 @@ const weatherState = ref({ fogDensity: 0 }) -// Scene lifecycle methods -const preloadScene = async (scene: Phaser.Scene) => { +// Scene setup +const preloadScene = (scene: Phaser.Scene) => { scene.load.image('raindrop', 'assets/raindrop.png') scene.load.image('fog', 'assets/fog.png') } -const createScene = async (scene: Phaser.Scene) => { +const createScene = (scene: Phaser.Scene) => { sceneRef.value = scene - setupEffects(scene) + initializeEffects(scene) setupSocketListeners() } -const updateScene = () => { - updateEffects() -} +const initializeEffects = (scene: Phaser.Scene) => { + // Light + effects.light.value = scene.add.graphics().setDepth(1000) -// Effect setup -const setupEffects = (scene: Phaser.Scene) => { - createLightEffect(scene) - createRainEffect(scene) - createFogEffect(scene) -} - -const createLightEffect = (scene: Phaser.Scene) => { - lightEffect.value = scene.add.graphics() - lightEffect.value.setDepth(1000) -} - -const createRainEffect = (scene: Phaser.Scene) => { - rainEmitter.value = scene.add.particles(0, 0, 'raindrop', { + // Rain + effects.rain.value = scene.add.particles(0, 0, 'raindrop', { x: { min: 0, max: window.innerWidth }, y: -50, quantity: 5, @@ -73,146 +63,101 @@ const createRainEffect = (scene: Phaser.Scene) => { scale: { start: 0.005, end: 0.005 }, alpha: { start: 0.5, end: 0 }, blendMode: 'ADD' - }) - rainEmitter.value.setDepth(900) - rainEmitter.value.stop() + }).setDepth(900) + effects.rain.value.stop() + + // Fog + effects.fog.value = scene.add.sprite(window.innerWidth / 2, window.innerHeight / 2, 'fog') + .setScale(2) + .setAlpha(0) + .setDepth(950) } -const createFogEffect = (scene: Phaser.Scene) => { - fogSprite.value = scene.add.sprite(window.innerWidth / 2, window.innerHeight / 2, 'fog') - fogSprite.value.setScale(2) - fogSprite.value.setAlpha(0) - fogSprite.value.setDepth(950) +// Effect updates +const updateScene = () => { + const timeBasedLight = calculateLightStrength(gameStore.world.date) + const zoneEffects = zoneStore.zone?.zoneEffects as Array<{ effect: string, strength: number }> + + if (zoneEffects?.length) { + applyEffects({ light: timeBasedLight }, ...zoneEffects) + } else { + applyEffects({ + light: timeBasedLight, + rain: weatherState.value.isRainEnabled ? weatherState.value.rainPercentage : 0, + fog: weatherState.value.isFogEnabled ? weatherState.value.fogDensity * 100 : 0 + }) + } +} + +const applyEffects = (effectValues: Record) => { + if (effects.light.value) { + const darkness = 1 - (effectValues.light ?? 100) / 100 + effects.light.value.clear() + .fillStyle(0x000000, darkness) + .fillRect(0, 0, window.innerWidth, window.innerHeight) + } + + if (effects.rain.value) { + const strength = effectValues.rain ?? 0 + strength > 0 + ? effects.rain.value.start().setQuantity(Math.floor((strength / 100) * 10)) + : effects.rain.value.stop() + } + + if (effects.fog.value) { + effects.fog.value.setAlpha((effectValues.fog ?? 0) / 100) + } } -// Lighting calculations const calculateLightStrength = (time: Date): number => { const hour = time.getHours() const minute = time.getMinutes() - let strength = DAY_STRENGTH + if (hour >= LIGHT_CONFIG.SUNSET_HOUR || hour < LIGHT_CONFIG.SUNRISE_HOUR) + return LIGHT_CONFIG.NIGHT_STRENGTH - // Night time (10 PM - 6 AM) - if (hour >= SUNSET_HOUR || hour < SUNRISE_HOUR) { - strength = NIGHT_STRENGTH - } - // Full daylight (7 AM - 7 PM) - else if (hour > SUNRISE_HOUR && hour < SUNSET_HOUR - 2) { - strength = DAY_STRENGTH - } - // Sunrise transition (6 AM - 7 AM) - else if (hour === SUNRISE_HOUR) { - strength = NIGHT_STRENGTH + ((DAY_STRENGTH - NIGHT_STRENGTH) * minute) / 60 - } - // Sunset transition (8 PM - 10 PM) - else if (hour >= SUNSET_HOUR - 2 && hour < SUNSET_HOUR) { - const totalMinutes = (hour - (SUNSET_HOUR - 2)) * 60 + minute - const transitionProgress = totalMinutes / 120 // 2 hours = 120 minutes - strength = DAY_STRENGTH - (DAY_STRENGTH - NIGHT_STRENGTH) * transitionProgress - } + if (hour > LIGHT_CONFIG.SUNRISE_HOUR && hour < LIGHT_CONFIG.SUNSET_HOUR - 2) + return LIGHT_CONFIG.DAY_STRENGTH - return strength + if (hour === LIGHT_CONFIG.SUNRISE_HOUR) + return LIGHT_CONFIG.NIGHT_STRENGTH + + ((LIGHT_CONFIG.DAY_STRENGTH - LIGHT_CONFIG.NIGHT_STRENGTH) * minute) / 60 + + const totalMinutes = (hour - (LIGHT_CONFIG.SUNSET_HOUR - 2)) * 60 + minute + return LIGHT_CONFIG.DAY_STRENGTH - + (LIGHT_CONFIG.DAY_STRENGTH - LIGHT_CONFIG.NIGHT_STRENGTH) * (totalMinutes / 120) } -// Effect updates -const updateEffects = () => { - const effects = zoneStore.zone?.zoneEffects || [] - - if (effects.length > 0) { - updateZoneEffects(effects) - } else { - // Make sure we're getting the current time - const lightStrength = calculateLightStrength(gameStore.world.date) - updateLightEffect(lightStrength) - updateWeatherEffects() - } -} - -const updateZoneEffects = (effects: any[]) => { - // Always update light based on time when zone effects are present - updateLightEffect(calculateLightStrength(gameStore.world.date)) - - effects.forEach((effect) => { - switch (effect.effect) { - case 'rain': - updateRainEffect(effect.strength) - break - case 'fog': - updateFogEffect(effect.strength) - break - } - }) -} - -const updateWeatherEffects = () => { - updateRainEffect(weatherState.value.isRainEnabled ? weatherState.value.rainPercentage : 0) - updateFogEffect(weatherState.value.isFogEnabled ? weatherState.value.fogDensity * 100 : 0) -} - -const updateLightEffect = (strength: number) => { - if (!lightEffect.value) return - const darkness = 1 - strength / 100 - lightEffect.value.clear() - lightEffect.value.fillStyle(0x000000, darkness) - lightEffect.value.fillRect(0, 0, window.innerWidth, window.innerHeight) -} - -const updateRainEffect = (strength: number) => { - if (!rainEmitter.value) return - if (strength > 0) { - rainEmitter.value.start() - rainEmitter.value.setQuantity(Math.floor((strength / 100) * 10)) - } else { - rainEmitter.value.stop() - } -} - -const updateFogEffect = (strength: number) => { - if (!fogSprite.value) return - fogSprite.value.setAlpha(strength / 100) -} - -// Socket handlers +// Socket and window handlers const setupSocketListeners = () => { - // Initial weather state gameStore.connection?.emit('weather', (response: WeatherState) => { - if (zoneStore.zone?.zoneEffects) return weatherState.value = response - updateEffects() + updateScene() }) - // Weather updates gameStore.connection?.on('weather', (data: WeatherState) => { weatherState.value = data - updateEffects() + updateScene() }) - // Time updates - gameStore.connection?.on('date', () => { - if (zoneStore.zone?.zoneEffects) return - updateEffects() - }) + gameStore.connection?.on('date', updateScene) } -const updateEffectWindowSize = () => { - if (rainEmitter.value) rainEmitter.value.updateConfig({ x: { min: 0, max: window.innerWidth } }) - if (fogSprite.value) { - fogSprite.value.setX(window.innerWidth / 2) - fogSprite.value.setY(window.innerHeight / 2) - } +const handleResize = () => { + if (effects.rain.value) + effects.rain.value.updateConfig({ x: { min: 0, max: window.innerWidth } }) + if (effects.fog.value) + effects.fog.value.setPosition(window.innerWidth / 2, window.innerHeight / 2) } -// Watchers -watch(() => zoneStore.zone?.zoneEffects, updateEffects, { deep: true }) +// Lifecycle +watch(() => zoneStore.zone?.zoneEffects, updateScene, { deep: true }) -onMounted(() => { - window.addEventListener('resize', updateEffectWindowSize) -}) +onMounted(() => window.addEventListener('resize', handleResize)) -// Cleanup onBeforeUnmount(() => { - window.removeEventListener('resize', updateEffectWindowSize) + window.removeEventListener('resize', handleResize) if (sceneRef.value) sceneRef.value.scene.remove('effects') gameStore.connection?.off('weather') }) - + \ No newline at end of file