This commit is contained in:
2025-12-13 00:02:38 +01:00
parent 93757fc8c4
commit 0b65d86e65
34 changed files with 13572 additions and 1210 deletions

View File

@@ -8,11 +8,11 @@ class VisualEnhancementSystem {
this.enabled = true;
// Sub-systems
this.animatedTextures = null;
this.weatherEffects = null;
this.lightingSystem = null;
this.shadowSystem = null;
this.fogOfWar = null;
this.animatedTextures = new Map();
this.weatherEffects = [];
this.lightSources = [];
this.shadows = [];
this.particles = [];
// Settings
this.settings = {
@@ -22,9 +22,16 @@ class VisualEnhancementSystem {
shadows: true,
fogOfWar: false,
particleQuality: 'high', // low, medium, high, ultra
animationQuality: 'high'
animationQuality: 'high',
screenShake: true,
transitions: true
};
// Animation timers
this.waterAnimTime = 0;
this.treeAnimTime = 0;
this.fireAnimTime = 0;
this.loadSettings();
this.init();
@@ -32,161 +39,277 @@ class VisualEnhancementSystem {
}
init() {
// Initialize sub-systems
this.initAnimatedTextures();
this.initWeatherEffects();
this.initLightingSystem();
this.initShadowSystem();
this.initParticleSystem();
}
/**
* Initialize animated textures
*/
// ========== ANIMATED TEXTURES ==========
initAnimatedTextures() {
if (!this.settings.animatedTextures) return;
// Crop growth animations
this.createCropAnimations();
// Water flow
// Create water animation frames
this.createWaterAnimation();
// Tree leaves
this.createTreeAnimations();
// Create fire animation
this.createFireAnimation();
// Fire effects
this.createFireAnimations();
// Create tree leaf animation
this.createTreeAnimation();
console.log('🎬 Animated textures initialized');
}
/**
* Create crop growth animations
*/
createCropAnimations() {
// Smooth transitions between growth stages
console.log('🌱 Creating crop animations...');
}
/**
* Create water animation
*/
createWaterAnimation() {
// Flowing water effect
console.log('💧 Creating water animation...');
// 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
});
}
/**
* Create tree animations
*/
createTreeAnimations() {
// Leaf rustling
console.log('🌳 Creating tree animations...');
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
});
}
/**
* Create fire animations
*/
createFireAnimations() {
// Flickering flames
console.log('🔥 Creating fire animations...');
createTreeAnimation() {
// Tree leaf rustling (subtle movement)
console.log('🌳 Tree animation ready');
}
/**
* Initialize weather effects
*/
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('🌦️ Initializing weather effects...');
// Snow accumulation
// Rain splashes
// Wind indicators
// Lightning
// Fog
console.log('🌦️ Weather effects initialized');
}
/**
* Initialize lighting system
*/
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()
});
}
// ========== LIGHTING SYSTEM ==========
initLightingSystem() {
if (!this.settings.dynamicLighting) return;
console.log('💡 Initializing lighting system...');
// Create lighting layer
this.lightingLayer = this.scene.add.layer();
this.lightingLayer.setDepth(5000);
// Light sources
this.lightSources = [];
console.log('💡 Lighting system initialized');
}
/**
* Add light source
*/
addLight(x, y, radius, color, intensity) {
const light = {
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,
sprite: null
flickering: false
};
// Create light sprite
const graphics = this.scene.add.graphics();
graphics.fillStyle(color, intensity);
graphics.fillCircle(0, 0, radius);
graphics.generateTexture('light_' + this.lightSources.length, radius * 2, radius * 2);
graphics.destroy();
light.sprite = this.scene.add.sprite(x, y, 'light_' + this.lightSources.length);
light.sprite.setBlendMode(Phaser.BlendModes.ADD);
light.sprite.setAlpha(intensity);
this.lightSources.push(light);
return light;
this.lightSources.push(lightObj);
return lightObj;
}
/**
* Initialize shadow system
*/
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('🌑 Initializing shadow system...');
this.shadows = [];
console.log('🌑 Shadow system initialized');
}
/**
* Add shadow to entity
*/
addShadow(entity, offsetX = 0, offsetY = 10) {
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,
entity.width * 0.8,
entity.height * 0.3,
width,
height,
0x000000,
0.3
);
shadow.setDepth(entity.depth - 1);
shadow.setDepth(0);
this.shadows.push({ entity, shadow, offsetX, offsetY });
const shadowObj = { entity, shadow, offsetX, offsetY };
this.shadows.push(shadowObj);
return shadow;
}
/**
* Update shadows based on time of day
*/
updateShadows() {
if (!this.settings.shadows) return;
// Get time of day
const timeOfDay = this.scene.weatherSystem ? this.scene.weatherSystem.gameTime : 12;
// 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;
}
// Calculate shadow opacity (darker at noon, lighter at dawn/dusk)
const opacity = Math.abs(Math.sin((timeOfDay / 24) * Math.PI)) * 0.5;
// Update all shadows
// Update shadow positions
for (const { entity, shadow, offsetX, offsetY } of this.shadows) {
if (entity.sprite) {
shadow.x = entity.sprite.x + offsetX;
@@ -196,47 +319,225 @@ class VisualEnhancementSystem {
}
}
/**
* Create screen shake effect
*/
// ========== 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);
}
/**
* Create fade transition
*/
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);
this.scene.cameras.main.once('camerafadeoutcomplete', callback);
}
/**
* Fade in
*/
fadeIn(duration = 500) {
this.scene.cameras.main.fadeIn(duration, 0, 0, 0);
}
/**
* Update (called every frame)
*/
update(delta) {
if (this.settings.shadows) {
this.updateShadows();
if (callback) {
this.scene.cameras.main.once('camerafadeoutcomplete', callback);
}
}
/**
* Save settings
*/
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));
}
/**
* Load settings
*/
loadSettings() {
const saved = localStorage.getItem('novafarma_visual_enhancements');
if (saved) {
@@ -244,14 +545,14 @@ class VisualEnhancementSystem {
}
}
/**
* Destroy system
*/
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');
}
}