Files
novafarma/src/systems/UIPolishSystem.js
NovaFarma Dev 8c0cc90908 PART 3: POLISH & EFFECTS - 100% COMPLETE! (Phase 29)
COMPLETED FEATURES:

PART 1: IMMEDIATE INTEGRATION (30 min)
-  Crafting system integration verified
-  Created comprehensive test plans
-  INTEGRATION_TEST_PLAN.md
-  QUICK_START_TEST.md

PART 3: POLISH & EFFECTS (2h 5min) - 100% DONE!

Phase 5C: Lighting & Shadows (20 min)
-  LightingSystem.js (215 lines)
- Dynamic player shadow with time-of-day opacity
- Auto-torch at night (flickering effect)
- Campfire creation API
- Light source management

Phase 5B: Enhanced Weather (25 min)
-  WeatherEnhancementsSystem.js (245 lines)
- Dynamic wind system (strength + direction)
- Wind affects rain particles
- Tree sway animations
- Smooth weather transitions (2s fade)
- Wind info API (speed km/h, compass)

Phase 5D: UI Polish (20 min)
-  UIPolishSystem.js (330 lines)
- Fade in/out & slide animations
- Button hover effects with sound
- Tooltips (auto + manual, cursor follow)
- Pulse, shake, flash animations
- Typewriter text effect
- Number counter animation
- Smooth scroll support

Phase 5E: Particle Effects (30 min)
-  ParticleEnhancementsSystem.js (450 lines)
- Craft sparkles (golden burst)
- Walk dust clouds (grass/dirt only)
- Harvest bursts (crop-colored!)
- Dig/till soil particles
- Plant sparkles
- Level up / damage / heal effects
- Integrated with CraftingSystem & FarmingSystem

 STATS:
- 4 new systems created (~1,240 lines)
- 5 documentation files
- 30+ new features
- 7 files modified
- Total time: 2h 35min

 GAME NOW HAS:
- Dynamic shadows & lighting
- Wind-affected weather
- Complete UI animation toolkit
- Enhanced particle effects for all actions

Files modified:
- index.html (4 new script tags)
- GameScene.js (4 system initializations + update calls)
- CraftingSystem.js (craft sparkles on completion)
- FarmingSystem.js (dig/plant/harvest particles)
- TASKS.md (Phase 29 updated)
- FINAL_IMPLEMENTATION_ROADMAP.md (PART 3 100% complete)
2025-12-15 16:42:09 +01:00

326 lines
8.8 KiB
JavaScript

// UI Polish System - Smooth transitions, animations, tooltips
class UIPolishSystem {
constructor(scene) {
this.scene = scene;
// Tooltip management
this.currentTooltip = null;
this.tooltipDelay = 500; // Show after 500ms hover
this.tooltipTimer = null;
// Button animations cache
this.buttonAnimations = new Map();
console.log('🎨 UIPolishSystem initialized');
}
// Fade in a UI element smoothly
fadeIn(element, duration = 300, delay = 0) {
if (!element) return;
element.setAlpha(0);
this.scene.tweens.add({
targets: element,
alpha: 1,
duration: duration,
delay: delay,
ease: 'Power2'
});
}
// Fade out a UI element
fadeOut(element, duration = 300, onComplete = null) {
if (!element) return;
this.scene.tweens.add({
targets: element,
alpha: 0,
duration: duration,
ease: 'Power2',
onComplete: onComplete
});
}
// Slide in element from direction
slideIn(element, direction = 'left', duration = 400, distance = 200) {
if (!element) return;
const startX = element.x;
const startY = element.y;
// Set starting position
switch (direction) {
case 'left':
element.x -= distance;
break;
case 'right':
element.x += distance;
break;
case 'top':
element.y -= distance;
break;
case 'bottom':
element.y += distance;
break;
}
element.setAlpha(0);
// Animate to original position
this.scene.tweens.add({
targets: element,
x: startX,
y: startY,
alpha: 1,
duration: duration,
ease: 'Back.easeOut'
});
}
// Add hover effect to button
addButtonHover(button, scaleUp = 1.1, duration = 200) {
if (!button || this.buttonAnimations.has(button)) return;
const originalScale = button.scaleX || 1;
// Mouse over
button.on('pointerover', () => {
this.scene.tweens.add({
targets: button,
scaleX: originalScale * scaleUp,
scaleY: originalScale * scaleUp,
duration: duration,
ease: 'Back.easeOut'
});
// Play UI click sound
if (this.scene.soundManager && this.scene.soundManager.beepUIClick) {
this.scene.soundManager.beepUIClick();
}
});
// Mouse out
button.on('pointerout', () => {
this.scene.tweens.add({
targets: button,
scaleX: originalScale,
scaleY: originalScale,
duration: duration,
ease: 'Power2'
});
});
this.buttonAnimations.set(button, { originalScale, scaleUp });
}
// Pulse animation (for important elements)
pulse(element, minScale = 0.95, maxScale = 1.05, duration = 1000) {
if (!element) return;
return this.scene.tweens.add({
targets: element,
scale: { from: minScale, to: maxScale },
duration: duration,
yoyo: true,
repeat: -1,
ease: 'Sine.easeInOut'
});
}
// Shake animation (for errors or attention)
shake(element, intensity = 10, duration = 500) {
if (!element) return;
const originalX = element.x;
this.scene.tweens.add({
targets: element,
x: originalX + intensity,
duration: 50,
yoyo: true,
repeat: Math.floor(duration / 100),
ease: 'Sine.easeInOut',
onComplete: () => {
element.x = originalX; // Reset to original position
}
});
}
// Show tooltip on hover
showTooltip(x, y, text, options = {}) {
// Clear existing tooltip
this.hideTooltip();
const {
backgroundColor = '#000000',
textColor = '#ffffff',
padding = 10,
fontSize = '14px',
maxWidth = 200,
offsetX = 10,
offsetY = -30
} = options;
// Create tooltip background
const bg = this.scene.add.rectangle(
x + offsetX,
y + offsetY,
maxWidth,
40,
Phaser.Display.Color.HexStringToColor(backgroundColor).color,
0.9
);
// Create tooltip text
const tooltip = this.scene.add.text(
x + offsetX,
y + offsetY,
text,
{
fontSize: fontSize,
color: textColor,
align: 'center',
wordWrap: { width: maxWidth - padding * 2 }
}
);
tooltip.setOrigin(0.5, 0.5);
bg.setSize(tooltip.width + padding * 2, tooltip.height + padding * 2);
// Create container
this.currentTooltip = this.scene.add.container(0, 0, [bg, tooltip]);
this.currentTooltip.setDepth(1000000); // Always on top
// Fade in
this.fadeIn(this.currentTooltip, 200);
}
// Hide current tooltip
hideTooltip() {
if (this.currentTooltip) {
this.fadeOut(this.currentTooltip, 150, () => {
this.currentTooltip.destroy();
this.currentTooltip = null;
});
}
}
// Add tooltip to interactive object
addTooltip(object, text, options = {}) {
if (!object) return;
let hoverTimer = null;
object.on('pointerover', (pointer) => {
// Delay tooltip appearance
hoverTimer = this.scene.time.delayedCall(this.tooltipDelay, () => {
this.showTooltip(pointer.worldX, pointer.worldY, text, options);
});
});
object.on('pointerout', () => {
// Cancel delayed tooltip
if (hoverTimer) {
hoverTimer.destroy();
hoverTimer = null;
}
this.hideTooltip();
});
object.on('pointermove', (pointer) => {
// Move tooltip with mouse
if (this.currentTooltip) {
this.currentTooltip.setPosition(
pointer.worldX + 10,
pointer.worldY - 30
);
}
});
}
// Typewriter text effect
typewriterText(textObject, fullText, speed = 50) {
if (!textObject) return;
textObject.setText('');
let index = 0;
const timer = this.scene.time.addEvent({
delay: speed,
callback: () => {
if (index < fullText.length) {
textObject.setText(textObject.text + fullText[index]);
index++;
} else {
timer.destroy();
}
},
loop: true
});
return timer;
}
// Number counter animation (for scores, resources)
animateNumber(textObject, startValue, endValue, duration = 1000, prefix = '', suffix = '') {
if (!textObject) return;
const data = { value: startValue };
this.scene.tweens.add({
targets: data,
value: endValue,
duration: duration,
ease: 'Power2',
onUpdate: () => {
textObject.setText(`${prefix}${Math.floor(data.value)}${suffix}`);
}
});
}
// Flash effect (for notifications)
flash(element, color = 0xffffff, duration = 300) {
if (!element) return;
const originalTint = element.tint || 0xffffff;
element.setTint(color);
this.scene.tweens.add({
targets: element,
alpha: { from: 1, to: 0.5 },
duration: duration / 2,
yoyo: true,
onComplete: () => {
element.setTint(originalTint);
}
});
}
// Smooth scroll container (for long lists)
enableSmoothScroll(container, scrollSpeed = 5) {
if (!container || !this.scene.input.keyboard) return;
const upKey = this.scene.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.UP);
const downKey = this.scene.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.DOWN);
this.scene.events.on('update', () => {
if (upKey.isDown) {
container.y += scrollSpeed;
}
if (downKey.isDown) {
container.y -= scrollSpeed;
}
});
}
// Clean up
destroy() {
this.hideTooltip();
this.buttonAnimations.clear();
console.log('🎨 UIPolishSystem destroyed');
}
}