forked from noxious/client
Overriding zone effects now works
This commit is contained in:
parent
8087f754b0
commit
857d56a878
@ -10,24 +10,26 @@ import { onBeforeUnmount, onMounted, ref, watch } from 'vue'
|
|||||||
import type { WeatherState } from '@/types'
|
import type { WeatherState } from '@/types'
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
const SUNRISE_HOUR = 6
|
const LIGHT_CONFIG = {
|
||||||
const SUNSET_HOUR = 20
|
SUNRISE_HOUR: 6,
|
||||||
const DAY_STRENGTH = 100
|
SUNSET_HOUR: 20,
|
||||||
const NIGHT_STRENGTH = 30
|
DAY_STRENGTH: 100,
|
||||||
|
NIGHT_STRENGTH: 30
|
||||||
|
}
|
||||||
|
|
||||||
// Stores
|
// Stores and refs
|
||||||
const gameStore = useGameStore()
|
const gameStore = useGameStore()
|
||||||
const zoneStore = useZoneStore()
|
const zoneStore = useZoneStore()
|
||||||
|
|
||||||
// Scene ref
|
|
||||||
const sceneRef = ref<Phaser.Scene | null>(null)
|
const sceneRef = ref<Phaser.Scene | null>(null)
|
||||||
|
|
||||||
// Effect refs
|
// Effect objects
|
||||||
const lightEffect = ref<Phaser.GameObjects.Graphics | null>(null)
|
const effects = {
|
||||||
const rainEmitter = ref<Phaser.GameObjects.Particles.ParticleEmitter | null>(null)
|
light: ref<Phaser.GameObjects.Graphics | null>(null),
|
||||||
const fogSprite = ref<Phaser.GameObjects.Sprite | null>(null)
|
rain: ref<Phaser.GameObjects.Particles.ParticleEmitter | null>(null),
|
||||||
|
fog: ref<Phaser.GameObjects.Sprite | null>(null)
|
||||||
|
}
|
||||||
|
|
||||||
// State refs
|
// Weather state
|
||||||
const weatherState = ref<WeatherState>({
|
const weatherState = ref<WeatherState>({
|
||||||
isRainEnabled: false,
|
isRainEnabled: false,
|
||||||
rainPercentage: 0,
|
rainPercentage: 0,
|
||||||
@ -35,36 +37,24 @@ const weatherState = ref<WeatherState>({
|
|||||||
fogDensity: 0
|
fogDensity: 0
|
||||||
})
|
})
|
||||||
|
|
||||||
// Scene lifecycle methods
|
// Scene setup
|
||||||
const preloadScene = async (scene: Phaser.Scene) => {
|
const preloadScene = (scene: Phaser.Scene) => {
|
||||||
scene.load.image('raindrop', 'assets/raindrop.png')
|
scene.load.image('raindrop', 'assets/raindrop.png')
|
||||||
scene.load.image('fog', 'assets/fog.png')
|
scene.load.image('fog', 'assets/fog.png')
|
||||||
}
|
}
|
||||||
|
|
||||||
const createScene = async (scene: Phaser.Scene) => {
|
const createScene = (scene: Phaser.Scene) => {
|
||||||
sceneRef.value = scene
|
sceneRef.value = scene
|
||||||
setupEffects(scene)
|
initializeEffects(scene)
|
||||||
setupSocketListeners()
|
setupSocketListeners()
|
||||||
}
|
}
|
||||||
|
|
||||||
const updateScene = () => {
|
const initializeEffects = (scene: Phaser.Scene) => {
|
||||||
updateEffects()
|
// Light
|
||||||
}
|
effects.light.value = scene.add.graphics().setDepth(1000)
|
||||||
|
|
||||||
// Effect setup
|
// Rain
|
||||||
const setupEffects = (scene: Phaser.Scene) => {
|
effects.rain.value = scene.add.particles(0, 0, 'raindrop', {
|
||||||
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', {
|
|
||||||
x: { min: 0, max: window.innerWidth },
|
x: { min: 0, max: window.innerWidth },
|
||||||
y: -50,
|
y: -50,
|
||||||
quantity: 5,
|
quantity: 5,
|
||||||
@ -73,145 +63,100 @@ const createRainEffect = (scene: Phaser.Scene) => {
|
|||||||
scale: { start: 0.005, end: 0.005 },
|
scale: { start: 0.005, end: 0.005 },
|
||||||
alpha: { start: 0.5, end: 0 },
|
alpha: { start: 0.5, end: 0 },
|
||||||
blendMode: 'ADD'
|
blendMode: 'ADD'
|
||||||
|
}).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)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
})
|
})
|
||||||
rainEmitter.value.setDepth(900)
|
}
|
||||||
rainEmitter.value.stop()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const createFogEffect = (scene: Phaser.Scene) => {
|
const applyEffects = (effectValues: Record<string, number>) => {
|
||||||
fogSprite.value = scene.add.sprite(window.innerWidth / 2, window.innerHeight / 2, 'fog')
|
if (effects.light.value) {
|
||||||
fogSprite.value.setScale(2)
|
const darkness = 1 - (effectValues.light ?? 100) / 100
|
||||||
fogSprite.value.setAlpha(0)
|
effects.light.value.clear()
|
||||||
fogSprite.value.setDepth(950)
|
.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 calculateLightStrength = (time: Date): number => {
|
||||||
const hour = time.getHours()
|
const hour = time.getHours()
|
||||||
const minute = time.getMinutes()
|
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 > LIGHT_CONFIG.SUNRISE_HOUR && hour < LIGHT_CONFIG.SUNSET_HOUR - 2)
|
||||||
if (hour >= SUNSET_HOUR || hour < SUNRISE_HOUR) {
|
return LIGHT_CONFIG.DAY_STRENGTH
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
// Socket and window handlers
|
||||||
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
|
|
||||||
const setupSocketListeners = () => {
|
const setupSocketListeners = () => {
|
||||||
// Initial weather state
|
|
||||||
gameStore.connection?.emit('weather', (response: WeatherState) => {
|
gameStore.connection?.emit('weather', (response: WeatherState) => {
|
||||||
if (zoneStore.zone?.zoneEffects) return
|
|
||||||
weatherState.value = response
|
weatherState.value = response
|
||||||
updateEffects()
|
updateScene()
|
||||||
})
|
})
|
||||||
|
|
||||||
// Weather updates
|
|
||||||
gameStore.connection?.on('weather', (data: WeatherState) => {
|
gameStore.connection?.on('weather', (data: WeatherState) => {
|
||||||
weatherState.value = data
|
weatherState.value = data
|
||||||
updateEffects()
|
updateScene()
|
||||||
})
|
})
|
||||||
|
|
||||||
// Time updates
|
gameStore.connection?.on('date', updateScene)
|
||||||
gameStore.connection?.on('date', () => {
|
|
||||||
if (zoneStore.zone?.zoneEffects) return
|
|
||||||
updateEffects()
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const updateEffectWindowSize = () => {
|
const handleResize = () => {
|
||||||
if (rainEmitter.value) rainEmitter.value.updateConfig({ x: { min: 0, max: window.innerWidth } })
|
if (effects.rain.value)
|
||||||
if (fogSprite.value) {
|
effects.rain.value.updateConfig({ x: { min: 0, max: window.innerWidth } })
|
||||||
fogSprite.value.setX(window.innerWidth / 2)
|
if (effects.fog.value)
|
||||||
fogSprite.value.setY(window.innerHeight / 2)
|
effects.fog.value.setPosition(window.innerWidth / 2, window.innerHeight / 2)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Watchers
|
// Lifecycle
|
||||||
watch(() => zoneStore.zone?.zoneEffects, updateEffects, { deep: true })
|
watch(() => zoneStore.zone?.zoneEffects, updateScene, { deep: true })
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => window.addEventListener('resize', handleResize))
|
||||||
window.addEventListener('resize', updateEffectWindowSize)
|
|
||||||
})
|
|
||||||
|
|
||||||
// Cleanup
|
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
window.removeEventListener('resize', updateEffectWindowSize)
|
window.removeEventListener('resize', handleResize)
|
||||||
if (sceneRef.value) sceneRef.value.scene.remove('effects')
|
if (sceneRef.value) sceneRef.value.scene.remove('effects')
|
||||||
gameStore.connection?.off('weather')
|
gameStore.connection?.off('weather')
|
||||||
})
|
})
|
||||||
|
Loading…
x
Reference in New Issue
Block a user