376 lines
12 KiB
JavaScript
376 lines
12 KiB
JavaScript
// Particle Enhancements System - Advanced particle effects for gameplay
|
|
class ParticleEnhancementsSystem {
|
|
constructor(scene) {
|
|
this.scene = scene;
|
|
|
|
// Particle pools for efficiency
|
|
this.sparklePool = [];
|
|
this.dustPool = [];
|
|
this.particleTextures = new Set();
|
|
|
|
// Create particle textures
|
|
this.createParticleTextures();
|
|
|
|
console.log('✨ ParticleEnhancementsSystem initialized');
|
|
}
|
|
|
|
// Create procedural particle textures
|
|
createParticleTextures() {
|
|
// Sparkle particle (star-shaped)
|
|
if (!this.scene.textures.exists('sparkle')) {
|
|
const graphics = this.scene.make.graphics({ x: 0, y: 0, add: false });
|
|
graphics.fillStyle(0xffffff, 1);
|
|
graphics.fillCircle(4, 4, 4);
|
|
graphics.generateTexture('sparkle', 8, 8);
|
|
graphics.destroy();
|
|
this.particleTextures.add('sparkle');
|
|
}
|
|
|
|
// Dust particle (cloud-shaped)
|
|
if (!this.scene.textures.exists('dust')) {
|
|
const graphics = this.scene.make.graphics({ x: 0, y: 0, add: false });
|
|
graphics.fillStyle(0xdddddd, 0.6);
|
|
graphics.fillCircle(3, 3, 3);
|
|
graphics.generateTexture('dust', 6, 6);
|
|
graphics.destroy();
|
|
this.particleTextures.add('dust');
|
|
}
|
|
|
|
// Leaf particle (for harvest)
|
|
if (!this.scene.textures.exists('leaf')) {
|
|
const graphics = this.scene.make.graphics({ x: 0, y: 0, add: false });
|
|
graphics.fillStyle(0x4a9d5f, 1);
|
|
graphics.fillRect(0, 0, 4, 6);
|
|
graphics.generateTexture('leaf', 4, 6);
|
|
graphics.destroy();
|
|
this.particleTextures.add('leaf');
|
|
}
|
|
|
|
// Star particle (for special effects)
|
|
if (!this.scene.textures.exists('star')) {
|
|
const graphics = this.scene.make.graphics({ x: 0, y: 0, add: false });
|
|
graphics.fillStyle(0xffee88, 1);
|
|
|
|
// 5-pointed star
|
|
const cx = 5, cy = 5, spikes = 5, outerRadius = 5, innerRadius = 2;
|
|
let rot = Math.PI / 2 * 3;
|
|
let x = cx;
|
|
let y = cy;
|
|
const step = Math.PI / spikes;
|
|
|
|
graphics.beginPath();
|
|
graphics.moveTo(cx, cy - outerRadius);
|
|
|
|
for (let i = 0; i < spikes; i++) {
|
|
x = cx + Math.cos(rot) * outerRadius;
|
|
y = cy + Math.sin(rot) * outerRadius;
|
|
graphics.lineTo(x, y);
|
|
rot += step;
|
|
|
|
x = cx + Math.cos(rot) * innerRadius;
|
|
y = cy + Math.sin(rot) * innerRadius;
|
|
graphics.lineTo(x, y);
|
|
rot += step;
|
|
}
|
|
|
|
graphics.lineTo(cx, cy - outerRadius);
|
|
graphics.closePath();
|
|
graphics.fillPath();
|
|
graphics.generateTexture('star', 10, 10);
|
|
graphics.destroy();
|
|
this.particleTextures.add('star');
|
|
}
|
|
}
|
|
|
|
// Enhanced craft sparkles (when crafting completes)
|
|
craftSparkles(x, y, color = [0xffffff, 0xffee88, 0xffaa00]) {
|
|
const emitter = this.scene.add.particles(x, y, 'sparkle', {
|
|
speed: { min: 50, max: 150 },
|
|
angle: { min: 0, max: 360 },
|
|
scale: { start: 1, end: 0 },
|
|
tint: color,
|
|
alpha: { start: 1, end: 0 },
|
|
lifespan: 1000,
|
|
quantity: 20,
|
|
blendMode: 'ADD',
|
|
emitting: false
|
|
});
|
|
|
|
emitter.setDepth(999999);
|
|
emitter.explode(20); // Burst of 20 particles
|
|
|
|
// Auto-destroy after particles fade
|
|
this.scene.time.delayedCall(1200, () => {
|
|
emitter.destroy();
|
|
});
|
|
|
|
return emitter;
|
|
}
|
|
|
|
// Walk dust clouds (when player walks)
|
|
walkDust(x, y, direction = 'down') {
|
|
// Only spawn on grass/dirt tiles
|
|
const tileSize = 48;
|
|
const tileX = Math.floor(x / tileSize);
|
|
const tileY = Math.floor(y / tileSize);
|
|
|
|
if (this.scene.terrainSystem) {
|
|
const tile = this.scene.terrainSystem.getTile(tileX, tileY);
|
|
if (!tile || (tile.type !== 'grass' && tile.type !== 'dirt')) {
|
|
return null; // No dust on water/pavement
|
|
}
|
|
}
|
|
|
|
const emitter = this.scene.add.particles(x, y + 10, 'dust', {
|
|
speed: { min: 10, max: 30 },
|
|
angle: { min: 0, max: 360 },
|
|
scale: { start: 0.5, end: 1.5 },
|
|
alpha: { start: 0.4, end: 0 },
|
|
lifespan: 500,
|
|
quantity: 2,
|
|
frequency: 100,
|
|
blendMode: 'NORMAL',
|
|
tint: 0xccaa88, // Dusty brown
|
|
emitting: false
|
|
});
|
|
|
|
emitter.setDepth(this.scene.player ? this.scene.player.sprite.depth - 1 : 100);
|
|
emitter.explode(2); // Small puff
|
|
|
|
// Auto-destroy
|
|
this.scene.time.delayedCall(600, () => {
|
|
emitter.destroy();
|
|
});
|
|
|
|
return emitter;
|
|
}
|
|
|
|
// Harvest particle burst (when harvesting crops)
|
|
harvestBurst(x, y, cropType = 'generic') {
|
|
// Determine particle color based on crop
|
|
let particleColors = [0x4a9d5f, 0x90EE90]; // Default green
|
|
let particleTexture = 'leaf';
|
|
|
|
if (cropType === 'wheat' || cropType === 'grain') {
|
|
particleColors = [0xFFD700, 0xFFA500]; // Golden
|
|
particleTexture = 'sparkle';
|
|
} else if (cropType === 'carrot' || cropType === 'root') {
|
|
particleColors = [0xFF6B35, 0xFFA500]; // Orange
|
|
particleTexture = 'leaf';
|
|
} else if (cropType === 'berry' || cropType === 'fruit') {
|
|
particleColors = [0xFF1744, 0xFF6B9D]; // Red/Pink
|
|
particleTexture = 'sparkle';
|
|
}
|
|
|
|
const emitter = this.scene.add.particles(x, y, particleTexture, {
|
|
speed: { min: 80, max: 150 },
|
|
angle: { min: -120, max: -60 }, // Upward spray
|
|
scale: { start: 1, end: 0.3 },
|
|
tint: particleColors,
|
|
alpha: { start: 1, end: 0 },
|
|
lifespan: 800,
|
|
quantity: 15,
|
|
gravityY: 200, // Gravity pull
|
|
blendMode: 'NORMAL',
|
|
emitting: false
|
|
});
|
|
|
|
emitter.setDepth(200000);
|
|
emitter.explode(15);
|
|
|
|
// Auto-destroy
|
|
this.scene.time.delayedCall(1000, () => {
|
|
emitter.destroy();
|
|
});
|
|
|
|
// Play success sound
|
|
if (this.scene.soundManager && this.scene.soundManager.beepPickup) {
|
|
this.scene.soundManager.beepPickup();
|
|
}
|
|
|
|
return emitter;
|
|
}
|
|
|
|
// Dig/Till soil particles (when using hoe)
|
|
digParticles(x, y) {
|
|
const emitter = this.scene.add.particles(x, y, 'dust', {
|
|
speed: { min: 40, max: 80 },
|
|
angle: { min: -140, max: -40 }, // Upward
|
|
scale: { start: 0.8, end: 0.2 },
|
|
alpha: { start: 0.6, end: 0 },
|
|
tint: [0x8b6f47, 0x6b4423], // Brown soil
|
|
lifespan: 600,
|
|
quantity: 10,
|
|
gravityY: 150,
|
|
blendMode: 'NORMAL',
|
|
emitting: false
|
|
});
|
|
|
|
emitter.setDepth(200000);
|
|
emitter.explode(10);
|
|
|
|
this.scene.time.delayedCall(800, () => {
|
|
emitter.destroy();
|
|
});
|
|
|
|
return emitter;
|
|
}
|
|
|
|
// Plant seed sparkle (when planting)
|
|
plantSparkle(x, y) {
|
|
const emitter = this.scene.add.particles(x, y, 'sparkle', {
|
|
speed: { min: 20, max: 50 },
|
|
angle: { min: 0, max: 360 },
|
|
scale: { start: 0.6, end: 0 },
|
|
tint: 0x90EE90, // Light green
|
|
alpha: { start: 0.8, end: 0 },
|
|
lifespan: 500,
|
|
quantity: 8,
|
|
blendMode: 'ADD',
|
|
emitting: false
|
|
});
|
|
|
|
emitter.setDepth(200000);
|
|
emitter.explode(8);
|
|
|
|
this.scene.time.delayedCall(600, () => {
|
|
emitter.destroy();
|
|
});
|
|
|
|
return emitter;
|
|
}
|
|
|
|
// Build completion effect (when placing building)
|
|
buildComplete(x, y, width = 48, height = 48) {
|
|
// Create corner sparkles
|
|
const corners = [
|
|
{ x: x - width / 2, y: y - height / 2 }, // Top-left
|
|
{ x: x + width / 2, y: y - height / 2 }, // Top-right
|
|
{ x: x - width / 2, y: y + height / 2 }, // Bottom-left
|
|
{ x: x + width / 2, y: y + height / 2 } // Bottom-right
|
|
];
|
|
|
|
corners.forEach((corner, index) => {
|
|
this.scene.time.delayedCall(index * 100, () => {
|
|
this.craftSparkles(corner.x, corner.y, [0xFFD700, 0xFFA500]);
|
|
});
|
|
});
|
|
|
|
// Center burst
|
|
this.scene.time.delayedCall(400, () => {
|
|
this.craftSparkles(x, y, [0xffffff, 0xFFD700]);
|
|
});
|
|
}
|
|
|
|
// Level up / achievement effect
|
|
levelUpEffect(x, y) {
|
|
// Ring explosion
|
|
const emitter = this.scene.add.particles(x, y, 'star', {
|
|
speed: { min: 100, max: 200 },
|
|
angle: { min: 0, max: 360 },
|
|
scale: { start: 1.5, end: 0 },
|
|
tint: [0xFFD700, 0xFFEE88, 0xFFFFFF],
|
|
alpha: { start: 1, end: 0 },
|
|
lifespan: 1500,
|
|
quantity: 30,
|
|
blendMode: 'ADD',
|
|
emitting: false
|
|
});
|
|
|
|
emitter.setDepth(999999);
|
|
emitter.explode(30);
|
|
|
|
// Upward rising stars
|
|
const rising = this.scene.add.particles(x, y, 'star', {
|
|
speedY: { min: -100, max: -50 },
|
|
speedX: { min: -20, max: 20 },
|
|
scale: { start: 0.8, end: 0 },
|
|
tint: 0xFFD700,
|
|
alpha: { start: 1, end: 0 },
|
|
lifespan: 2000,
|
|
quantity: 1,
|
|
frequency: 100,
|
|
blendMode: 'ADD'
|
|
});
|
|
|
|
rising.setDepth(999999);
|
|
|
|
// Stop after 2 seconds
|
|
this.scene.time.delayedCall(2000, () => {
|
|
rising.stop();
|
|
});
|
|
|
|
// Cleanup
|
|
this.scene.time.delayedCall(3500, () => {
|
|
emitter.destroy();
|
|
rising.destroy();
|
|
});
|
|
|
|
return { burst: emitter, rising };
|
|
}
|
|
|
|
// Damage impact effect (when hit)
|
|
damageImpact(x, y, color = 0xFF0000) {
|
|
const emitter = this.scene.add.particles(x, y, 'sparkle', {
|
|
speed: { min: 50, max: 100 },
|
|
angle: { min: 0, max: 360 },
|
|
scale: { start: 0.8, end: 0 },
|
|
tint: color,
|
|
alpha: { start: 1, end: 0 },
|
|
lifespan: 400,
|
|
quantity: 12,
|
|
blendMode: 'ADD',
|
|
emitting: false
|
|
});
|
|
|
|
emitter.setDepth(999999);
|
|
emitter.explode(12);
|
|
|
|
this.scene.time.delayedCall(500, () => {
|
|
emitter.destroy();
|
|
});
|
|
|
|
return emitter;
|
|
}
|
|
|
|
// Heal/Restore effect
|
|
healEffect(x, y) {
|
|
const emitter = this.scene.add.particles(x, y, 'sparkle', {
|
|
speedY: { min: -80, max: -40 },
|
|
speedX: { min: -20, max: 20 },
|
|
scale: { start: 0.6, end: 0 },
|
|
tint: [0x00FF00, 0x90EE90, 0xFFFFFF],
|
|
alpha: { start: 1, end: 0 },
|
|
lifespan: 1000,
|
|
quantity: 1,
|
|
frequency: 80,
|
|
blendMode: 'ADD'
|
|
});
|
|
|
|
emitter.setDepth(999999);
|
|
|
|
this.scene.time.delayedCall(1000, () => {
|
|
emitter.stop();
|
|
});
|
|
|
|
this.scene.time.delayedCall(2000, () => {
|
|
emitter.destroy();
|
|
});
|
|
|
|
return emitter;
|
|
}
|
|
|
|
// Clean up all particles
|
|
destroy() {
|
|
// Destroy created textures
|
|
for (const textureName of this.particleTextures) {
|
|
if (this.scene.textures.exists(textureName)) {
|
|
this.scene.textures.remove(textureName);
|
|
}
|
|
}
|
|
this.particleTextures.clear();
|
|
|
|
console.log('✨ ParticleEnhancementsSystem destroyed');
|
|
}
|
|
}
|