ok
This commit is contained in:
624
DEBUG_TOTAL_RECOVERY/VisualEnhancementSystem.js
Normal file
624
DEBUG_TOTAL_RECOVERY/VisualEnhancementSystem.js
Normal file
@@ -0,0 +1,624 @@
|
||||
/**
|
||||
* VISUAL ENHANCEMENT SYSTEM
|
||||
* Central system for managing visual effects, animations, and polish
|
||||
*/
|
||||
class VisualEnhancementSystem {
|
||||
constructor(scene) {
|
||||
this.scene = scene;
|
||||
this.enabled = true;
|
||||
|
||||
// Sub-systems
|
||||
this.animatedTextures = new Map();
|
||||
this.weatherEffects = [];
|
||||
this.lightSources = [];
|
||||
this.shadows = [];
|
||||
this.particles = [];
|
||||
|
||||
// Settings
|
||||
this.settings = {
|
||||
animatedTextures: true,
|
||||
weatherEffects: true,
|
||||
dynamicLighting: true,
|
||||
shadows: true,
|
||||
fogOfWar: false,
|
||||
particleQuality: 'high', // low, medium, high, ultra
|
||||
animationQuality: 'high',
|
||||
screenShake: true,
|
||||
transitions: true
|
||||
};
|
||||
|
||||
// Animation timers
|
||||
this.waterAnimTime = 0;
|
||||
this.treeAnimTime = 0;
|
||||
this.fireAnimTime = 0;
|
||||
|
||||
this.loadSettings();
|
||||
this.init();
|
||||
|
||||
console.log('✅ Visual Enhancement System initialized');
|
||||
}
|
||||
|
||||
init() {
|
||||
this.initAnimatedTextures();
|
||||
this.initWeatherEffects();
|
||||
this.initLightingSystem();
|
||||
this.initShadowSystem();
|
||||
this.initParticleSystem();
|
||||
}
|
||||
|
||||
// ========== ANIMATED TEXTURES ==========
|
||||
|
||||
initAnimatedTextures() {
|
||||
if (!this.settings.animatedTextures) return;
|
||||
|
||||
// Create water animation frames
|
||||
this.createWaterAnimation();
|
||||
|
||||
// Create fire animation
|
||||
this.createFireAnimation();
|
||||
|
||||
// Create tree leaf animation
|
||||
this.createTreeAnimation();
|
||||
|
||||
console.log('🎬 Animated textures initialized');
|
||||
}
|
||||
|
||||
createWaterAnimation() {
|
||||
// Water flow animation (4 frames)
|
||||
const frames = [];
|
||||
for (let i = 0; i < 4; i++) {
|
||||
const graphics = this.scene.add.graphics();
|
||||
graphics.fillStyle(0x4488ff, 1);
|
||||
graphics.fillRect(0, 0, 64, 64);
|
||||
|
||||
// Add wave pattern
|
||||
graphics.lineStyle(2, 0x6699ff, 0.5);
|
||||
for (let y = 0; y < 64; y += 8) {
|
||||
const offset = Math.sin((y + i * 16) * 0.1) * 4;
|
||||
graphics.lineBetween(0, y + offset, 64, y + offset);
|
||||
}
|
||||
|
||||
graphics.generateTexture('water_anim_' + i, 64, 64);
|
||||
graphics.destroy();
|
||||
frames.push('water_anim_' + i);
|
||||
}
|
||||
|
||||
this.animatedTextures.set('water', {
|
||||
frames,
|
||||
currentFrame: 0,
|
||||
speed: 200 // ms per frame
|
||||
});
|
||||
}
|
||||
|
||||
createFireAnimation() {
|
||||
// Fire flickering (3 frames)
|
||||
const frames = [];
|
||||
const colors = [0xff6600, 0xff8800, 0xffaa00];
|
||||
|
||||
for (let i = 0; i < 3; i++) {
|
||||
const graphics = this.scene.add.graphics();
|
||||
graphics.fillStyle(colors[i], 1);
|
||||
graphics.fillCircle(16, 16, 12 + i * 2);
|
||||
graphics.generateTexture('fire_anim_' + i, 32, 32);
|
||||
graphics.destroy();
|
||||
frames.push('fire_anim_' + i);
|
||||
}
|
||||
|
||||
this.animatedTextures.set('fire', {
|
||||
frames,
|
||||
currentFrame: 0,
|
||||
speed: 150
|
||||
});
|
||||
}
|
||||
|
||||
createTreeAnimation() {
|
||||
// Tree leaf rustling (subtle movement)
|
||||
console.log('🌳 Tree animation ready');
|
||||
}
|
||||
|
||||
updateAnimatedTextures(delta) {
|
||||
if (!this.settings.animatedTextures) return;
|
||||
|
||||
this.waterAnimTime += delta;
|
||||
this.fireAnimTime += delta;
|
||||
|
||||
// Update water
|
||||
const water = this.animatedTextures.get('water');
|
||||
if (water && this.waterAnimTime > water.speed) {
|
||||
water.currentFrame = (water.currentFrame + 1) % water.frames.length;
|
||||
this.waterAnimTime = 0;
|
||||
}
|
||||
|
||||
// Update fire
|
||||
const fire = this.animatedTextures.get('fire');
|
||||
if (fire && this.fireAnimTime > fire.speed) {
|
||||
fire.currentFrame = (fire.currentFrame + 1) % fire.frames.length;
|
||||
this.fireAnimTime = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// ========== WEATHER EFFECTS ==========
|
||||
|
||||
initWeatherEffects() {
|
||||
if (!this.settings.weatherEffects) return;
|
||||
console.log('🌦️ Weather effects initialized');
|
||||
}
|
||||
|
||||
createSnowEffect() {
|
||||
const emitter = this.scene.add.particles(0, 0, 'particle_white', {
|
||||
x: { min: 0, max: this.scene.cameras.main.width },
|
||||
y: -10,
|
||||
speedY: { min: 50, max: 100 },
|
||||
speedX: { min: -20, max: 20 },
|
||||
scale: { min: 0.3, max: 0.8 },
|
||||
alpha: { min: 0.5, max: 1 },
|
||||
lifespan: 10000,
|
||||
frequency: 50,
|
||||
quantity: 2
|
||||
});
|
||||
emitter.setScrollFactor(0);
|
||||
this.weatherEffects.push(emitter);
|
||||
return emitter;
|
||||
}
|
||||
|
||||
createRainEffect() {
|
||||
const emitter = this.scene.add.particles(0, 0, 'particle_white', {
|
||||
x: { min: 0, max: this.scene.cameras.main.width },
|
||||
y: -10,
|
||||
speedY: { min: 400, max: 600 },
|
||||
speedX: { min: -50, max: -30 },
|
||||
scaleX: 0.1,
|
||||
scaleY: 0.5,
|
||||
alpha: 0.6,
|
||||
lifespan: 2000,
|
||||
frequency: 10,
|
||||
quantity: 5,
|
||||
tint: 0x88ccff
|
||||
});
|
||||
emitter.setScrollFactor(0);
|
||||
this.weatherEffects.push(emitter);
|
||||
return emitter;
|
||||
}
|
||||
|
||||
createLightningFlash() {
|
||||
const flash = this.scene.add.rectangle(
|
||||
this.scene.cameras.main.centerX,
|
||||
this.scene.cameras.main.centerY,
|
||||
this.scene.cameras.main.width,
|
||||
this.scene.cameras.main.height,
|
||||
0xffffff,
|
||||
0.8
|
||||
);
|
||||
flash.setScrollFactor(0);
|
||||
flash.setDepth(10000);
|
||||
|
||||
this.scene.tweens.add({
|
||||
targets: flash,
|
||||
alpha: 0,
|
||||
duration: 200,
|
||||
onComplete: () => flash.destroy()
|
||||
});
|
||||
}
|
||||
|
||||
createFogEffect() {
|
||||
// Atmospheric fog overlay - covers entire screen
|
||||
const fogOverlay = this.scene.add.graphics();
|
||||
fogOverlay.setScrollFactor(0);
|
||||
fogOverlay.setDepth(8000); // Above game, below UI
|
||||
fogOverlay.setAlpha(0.4); // Semi-transparent
|
||||
|
||||
// Create fog particles for movement effect
|
||||
const fogParticles = this.scene.add.particles(0, 0, 'particle_white', {
|
||||
x: { min: 0, max: this.scene.cameras.main.width },
|
||||
y: { min: 0, max: this.scene.cameras.main.height },
|
||||
speedX: { min: -10, max: 10 },
|
||||
speedY: { min: -5, max: 5 },
|
||||
scale: { min: 2, max: 4 },
|
||||
alpha: { min: 0.1, max: 0.3 },
|
||||
lifespan: 10000,
|
||||
frequency: 100,
|
||||
quantity: 3,
|
||||
tint: 0xcccccc,
|
||||
blendMode: 'SCREEN'
|
||||
});
|
||||
fogParticles.setScrollFactor(0);
|
||||
fogParticles.setDepth(8001);
|
||||
|
||||
// Animated fog overlay
|
||||
let fogTime = 0;
|
||||
const updateFog = () => {
|
||||
fogTime += 0.01;
|
||||
fogOverlay.clear();
|
||||
|
||||
const cam = this.scene.cameras.main;
|
||||
|
||||
// Draw multiple layers of fog for depth
|
||||
for (let layer = 0; layer < 3; layer++) {
|
||||
const offset = Math.sin(fogTime + layer) * 50;
|
||||
const alpha = 0.1 + layer * 0.05;
|
||||
|
||||
fogOverlay.fillStyle(0xffffff, alpha);
|
||||
|
||||
// Draw wavy fog shapes
|
||||
for (let i = 0; i < 5; i++) {
|
||||
const x = (i * cam.width / 4) + offset;
|
||||
const y = (layer * 100) + Math.cos(fogTime + i) * 30;
|
||||
fogOverlay.fillCircle(x, y, 200 + layer * 50);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Update fog animation every frame
|
||||
this.scene.events.on('update', updateFog);
|
||||
|
||||
this.weatherEffects.push({
|
||||
overlay: fogOverlay,
|
||||
particles: fogParticles,
|
||||
update: updateFog,
|
||||
destroy: () => {
|
||||
fogOverlay.destroy();
|
||||
fogParticles.destroy();
|
||||
this.scene.events.off('update', updateFog);
|
||||
}
|
||||
});
|
||||
|
||||
console.log('🌫️ Atmospheric fog effect created');
|
||||
return { overlay: fogOverlay, particles: fogParticles };
|
||||
}
|
||||
|
||||
// ========== LIGHTING SYSTEM ==========
|
||||
|
||||
initLightingSystem() {
|
||||
if (!this.settings.dynamicLighting) return;
|
||||
|
||||
this.lightingLayer = this.scene.add.layer();
|
||||
this.lightingLayer.setDepth(5000);
|
||||
|
||||
console.log('💡 Lighting system initialized');
|
||||
}
|
||||
|
||||
addLight(x, y, radius = 100, color = 0xffaa00, intensity = 0.6) {
|
||||
if (!this.settings.dynamicLighting) return null;
|
||||
|
||||
// Create radial gradient light
|
||||
const light = this.scene.add.graphics();
|
||||
const gradient = light.createRadialGradient(
|
||||
radius, radius, 0,
|
||||
radius, radius, radius
|
||||
);
|
||||
|
||||
gradient.addColorStop(0, `rgba(${(color >> 16) & 0xff}, ${(color >> 8) & 0xff}, ${color & 0xff}, ${intensity})`);
|
||||
gradient.addColorStop(1, 'rgba(0, 0, 0, 0)');
|
||||
|
||||
light.fillStyle(color, intensity);
|
||||
light.fillCircle(radius, radius, radius);
|
||||
light.setPosition(x - radius, y - radius);
|
||||
light.setBlendMode(Phaser.BlendModes.ADD);
|
||||
light.setDepth(5001);
|
||||
|
||||
const lightObj = {
|
||||
graphics: light,
|
||||
x, y, radius, color, intensity,
|
||||
flickering: false
|
||||
};
|
||||
|
||||
this.lightSources.push(lightObj);
|
||||
return lightObj;
|
||||
}
|
||||
|
||||
addTorch(x, y) {
|
||||
const torch = this.addLight(x, y, 80, 0xff6600, 0.5);
|
||||
if (torch) {
|
||||
torch.flickering = true;
|
||||
}
|
||||
return torch;
|
||||
}
|
||||
|
||||
updateLighting(delta) {
|
||||
if (!this.settings.dynamicLighting) return;
|
||||
|
||||
// Update flickering lights
|
||||
for (const light of this.lightSources) {
|
||||
if (light.flickering) {
|
||||
const flicker = 0.4 + Math.random() * 0.2;
|
||||
light.graphics.setAlpha(flicker);
|
||||
}
|
||||
}
|
||||
|
||||
// Update ambient lighting based on time of day
|
||||
if (this.scene.weatherSystem) {
|
||||
const time = this.scene.weatherSystem.gameTime;
|
||||
const isNight = time < 6 || time > 18;
|
||||
|
||||
if (isNight) {
|
||||
// Darker at night
|
||||
this.scene.cameras.main.setAlpha(0.7);
|
||||
} else {
|
||||
this.scene.cameras.main.setAlpha(1.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ========== SHADOW SYSTEM ==========
|
||||
|
||||
initShadowSystem() {
|
||||
if (!this.settings.shadows) return;
|
||||
console.log('🌑 Shadow system initialized');
|
||||
}
|
||||
|
||||
addShadow(entity, offsetX = 0, offsetY = 10, width = 40, height = 15) {
|
||||
if (!this.settings.shadows) return null;
|
||||
|
||||
const shadow = this.scene.add.ellipse(
|
||||
entity.x + offsetX,
|
||||
entity.y + offsetY,
|
||||
width,
|
||||
height,
|
||||
0x000000,
|
||||
0.3
|
||||
);
|
||||
shadow.setDepth(0);
|
||||
|
||||
const shadowObj = { entity, shadow, offsetX, offsetY };
|
||||
this.shadows.push(shadowObj);
|
||||
return shadow;
|
||||
}
|
||||
|
||||
updateShadows() {
|
||||
if (!this.settings.shadows) return;
|
||||
|
||||
// Get time of day for shadow opacity
|
||||
let opacity = 0.3;
|
||||
if (this.scene.weatherSystem) {
|
||||
const time = this.scene.weatherSystem.gameTime;
|
||||
// Darker shadows at noon, lighter at dawn/dusk
|
||||
opacity = 0.2 + Math.abs(Math.sin((time / 24) * Math.PI * 2)) * 0.3;
|
||||
}
|
||||
|
||||
// Update shadow positions
|
||||
for (const { entity, shadow, offsetX, offsetY } of this.shadows) {
|
||||
if (entity.sprite) {
|
||||
shadow.x = entity.sprite.x + offsetX;
|
||||
shadow.y = entity.sprite.y + offsetY;
|
||||
shadow.setAlpha(opacity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ========== PARTICLE SYSTEM ==========
|
||||
|
||||
initParticleSystem() {
|
||||
// Create particle textures
|
||||
this.createParticleTextures();
|
||||
console.log('✨ Particle system initialized');
|
||||
}
|
||||
|
||||
createParticleTextures() {
|
||||
// White particle
|
||||
const white = this.scene.add.graphics();
|
||||
white.fillStyle(0xffffff, 1);
|
||||
white.fillCircle(4, 4, 4);
|
||||
white.generateTexture('particle_white', 8, 8);
|
||||
white.destroy();
|
||||
|
||||
// Sparkle
|
||||
const sparkle = this.scene.add.graphics();
|
||||
sparkle.fillStyle(0xffff00, 1);
|
||||
sparkle.fillCircle(3, 3, 3);
|
||||
sparkle.generateTexture('particle_sparkle', 6, 6);
|
||||
sparkle.destroy();
|
||||
|
||||
// Heart
|
||||
const heart = this.scene.add.graphics();
|
||||
heart.fillStyle(0xff0066, 1);
|
||||
heart.fillCircle(3, 3, 3);
|
||||
heart.fillCircle(5, 3, 3);
|
||||
heart.fillTriangle(1, 4, 7, 4, 4, 8);
|
||||
heart.generateTexture('particle_heart', 8, 8);
|
||||
heart.destroy();
|
||||
}
|
||||
|
||||
createHeartParticles(x, y) {
|
||||
const emitter = this.scene.add.particles(x, y, 'particle_heart', {
|
||||
speed: { min: 20, max: 50 },
|
||||
angle: { min: -120, max: -60 },
|
||||
scale: { start: 1, end: 0 },
|
||||
alpha: { start: 1, end: 0 },
|
||||
lifespan: 1000,
|
||||
quantity: 5,
|
||||
blendMode: 'ADD'
|
||||
});
|
||||
|
||||
this.scene.time.delayedCall(1000, () => emitter.destroy());
|
||||
return emitter;
|
||||
}
|
||||
|
||||
createSparkleEffect(x, y) {
|
||||
const emitter = this.scene.add.particles(x, y, 'particle_sparkle', {
|
||||
speed: { min: 10, max: 30 },
|
||||
scale: { start: 1, end: 0 },
|
||||
alpha: { start: 1, end: 0 },
|
||||
lifespan: 800,
|
||||
quantity: 10,
|
||||
blendMode: 'ADD'
|
||||
});
|
||||
|
||||
this.scene.time.delayedCall(800, () => emitter.destroy());
|
||||
return emitter;
|
||||
}
|
||||
|
||||
createCheckmarkEffect(x, y) {
|
||||
const checkmark = this.scene.add.text(x, y, '✓', {
|
||||
fontSize: '32px',
|
||||
color: '#00ff00',
|
||||
fontStyle: 'bold'
|
||||
});
|
||||
checkmark.setOrigin(0.5);
|
||||
checkmark.setDepth(10000);
|
||||
|
||||
this.scene.tweens.add({
|
||||
targets: checkmark,
|
||||
y: y - 50,
|
||||
alpha: 0,
|
||||
scale: 2,
|
||||
duration: 1000,
|
||||
ease: 'Power2',
|
||||
onComplete: () => checkmark.destroy()
|
||||
});
|
||||
}
|
||||
|
||||
// ========== SCREEN EFFECTS ==========
|
||||
|
||||
screenShake(intensity = 10, duration = 300) {
|
||||
if (!this.settings.screenShake) return;
|
||||
this.scene.cameras.main.shake(duration, intensity / 1000);
|
||||
}
|
||||
|
||||
screenFlash(color = 0xffffff, duration = 200) {
|
||||
this.scene.cameras.main.flash(duration,
|
||||
(color >> 16) & 0xff,
|
||||
(color >> 8) & 0xff,
|
||||
color & 0xff
|
||||
);
|
||||
}
|
||||
|
||||
fadeOut(duration = 500, callback) {
|
||||
if (!this.settings.transitions) {
|
||||
if (callback) callback();
|
||||
return;
|
||||
}
|
||||
|
||||
this.scene.cameras.main.fadeOut(duration, 0, 0, 0);
|
||||
if (callback) {
|
||||
this.scene.cameras.main.once('camerafadeoutcomplete', callback);
|
||||
}
|
||||
}
|
||||
|
||||
fadeIn(duration = 500) {
|
||||
if (!this.settings.transitions) return;
|
||||
this.scene.cameras.main.fadeIn(duration, 0, 0, 0);
|
||||
}
|
||||
|
||||
// ========== BUILDING EFFECTS ==========
|
||||
|
||||
createConstructionEffect(x, y) {
|
||||
// Dust particles during construction
|
||||
const emitter = this.scene.add.particles(x, y, 'particle_white', {
|
||||
speed: { min: 20, max: 40 },
|
||||
scale: { start: 0.5, end: 0 },
|
||||
alpha: { start: 0.5, end: 0 },
|
||||
lifespan: 1000,
|
||||
quantity: 3,
|
||||
frequency: 100,
|
||||
tint: 0x996633
|
||||
});
|
||||
|
||||
return emitter;
|
||||
}
|
||||
|
||||
createSmokeEffect(x, y) {
|
||||
// Chimney smoke
|
||||
const emitter = this.scene.add.particles(x, y, 'particle_white', {
|
||||
speedY: { min: -30, max: -50 },
|
||||
speedX: { min: -10, max: 10 },
|
||||
scale: { start: 0.3, end: 1 },
|
||||
alpha: { start: 0.5, end: 0 },
|
||||
lifespan: 2000,
|
||||
frequency: 500,
|
||||
quantity: 1,
|
||||
tint: 0x888888
|
||||
});
|
||||
|
||||
return emitter;
|
||||
}
|
||||
|
||||
// ========== FARM AUTOMATION VISUALS ==========
|
||||
|
||||
createPowerGridEffect(x1, y1, x2, y2) {
|
||||
// Electric arc between power sources
|
||||
const graphics = this.scene.add.graphics();
|
||||
graphics.lineStyle(2, 0x00ffff, 0.8);
|
||||
|
||||
// Draw lightning-like connection
|
||||
const steps = 5;
|
||||
const points = [];
|
||||
for (let i = 0; i <= steps; i++) {
|
||||
const t = i / steps;
|
||||
const x = x1 + (x2 - x1) * t + (Math.random() - 0.5) * 10;
|
||||
const y = y1 + (y2 - y1) * t + (Math.random() - 0.5) * 10;
|
||||
points.push({ x, y });
|
||||
}
|
||||
|
||||
graphics.beginPath();
|
||||
graphics.moveTo(points[0].x, points[0].y);
|
||||
for (let i = 1; i < points.length; i++) {
|
||||
graphics.lineTo(points[i].x, points[i].y);
|
||||
}
|
||||
graphics.strokePath();
|
||||
|
||||
// Fade out
|
||||
this.scene.tweens.add({
|
||||
targets: graphics,
|
||||
alpha: 0,
|
||||
duration: 200,
|
||||
onComplete: () => graphics.destroy()
|
||||
});
|
||||
}
|
||||
|
||||
createMutantGlow(entity, color = 0x00ff00) {
|
||||
// Radioactive glow for mutants
|
||||
const glow = this.scene.add.circle(
|
||||
entity.x,
|
||||
entity.y,
|
||||
30,
|
||||
color,
|
||||
0.3
|
||||
);
|
||||
glow.setBlendMode(Phaser.BlendModes.ADD);
|
||||
glow.setDepth(entity.depth - 1);
|
||||
|
||||
// Pulsing animation
|
||||
this.scene.tweens.add({
|
||||
targets: glow,
|
||||
scale: { from: 1, to: 1.2 },
|
||||
alpha: { from: 0.3, to: 0.1 },
|
||||
duration: 1000,
|
||||
yoyo: true,
|
||||
repeat: -1
|
||||
});
|
||||
|
||||
return glow;
|
||||
}
|
||||
|
||||
// ========== UPDATE ==========
|
||||
|
||||
update(delta) {
|
||||
this.updateAnimatedTextures(delta);
|
||||
this.updateLighting(delta);
|
||||
this.updateShadows();
|
||||
}
|
||||
|
||||
// ========== SETTINGS ==========
|
||||
|
||||
saveSettings() {
|
||||
localStorage.setItem('novafarma_visual_enhancements', JSON.stringify(this.settings));
|
||||
}
|
||||
|
||||
loadSettings() {
|
||||
const saved = localStorage.getItem('novafarma_visual_enhancements');
|
||||
if (saved) {
|
||||
this.settings = { ...this.settings, ...JSON.parse(saved) };
|
||||
}
|
||||
}
|
||||
|
||||
destroy() {
|
||||
if (this.lightingLayer) this.lightingLayer.destroy();
|
||||
for (const { shadow } of this.shadows) {
|
||||
shadow.destroy();
|
||||
}
|
||||
for (const effect of this.weatherEffects) {
|
||||
effect.destroy();
|
||||
}
|
||||
console.log('✨ Visual Enhancement System destroyed');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user