575 lines
16 KiB
JavaScript
575 lines
16 KiB
JavaScript
/**
|
|
* UI GRAPHICS ENHANCEMENT SYSTEM
|
|
* High-resolution icons, animated UI elements, custom cursors, and achievements
|
|
*/
|
|
class UIGraphicsSystem {
|
|
constructor(scene) {
|
|
this.scene = scene;
|
|
this.enabled = true;
|
|
|
|
// Icon resolution
|
|
this.iconSize = 64; // 64x64 (upgraded from 32x32)
|
|
this.iconCache = new Map();
|
|
|
|
// Animated UI elements
|
|
this.animatedElements = [];
|
|
this.pulsingElements = [];
|
|
this.glowingElements = [];
|
|
|
|
// Custom cursors
|
|
this.cursors = {
|
|
'default': 'default',
|
|
'pointer': 'pointer',
|
|
'grab': 'grab',
|
|
'grabbing': 'grabbing',
|
|
'sword': 'url(data:image/png;base64,...) 16 16, auto',
|
|
'pickaxe': 'url(data:image/png;base64,...) 16 16, auto'
|
|
};
|
|
this.currentCursor = 'default';
|
|
|
|
// Achievement system
|
|
this.achievements = new Map();
|
|
this.unlockedAchievements = new Set();
|
|
|
|
// Loading screen
|
|
this.loadingScreen = null;
|
|
this.loadingProgress = 0;
|
|
|
|
// Settings
|
|
this.settings = {
|
|
highResIcons: true,
|
|
animatedUI: true,
|
|
customCursors: true,
|
|
achievementNotifications: true,
|
|
loadingArtwork: true
|
|
};
|
|
|
|
this.loadSettings();
|
|
this.init();
|
|
|
|
console.log('✅ UI Graphics System initialized');
|
|
}
|
|
|
|
init() {
|
|
// Generate high-res icons
|
|
if (this.settings.highResIcons) {
|
|
this.generateHighResIcons();
|
|
}
|
|
|
|
// Set up custom cursors
|
|
if (this.settings.customCursors) {
|
|
this.setupCustomCursors();
|
|
}
|
|
|
|
// Initialize achievements
|
|
this.initAchievements();
|
|
|
|
console.log('🎨 UI Graphics enhanced');
|
|
}
|
|
|
|
// ========== HIGH-RES ICONS ==========
|
|
|
|
generateHighResIcons() {
|
|
// Generate 64x64 icons for common items
|
|
const items = [
|
|
'wood', 'stone', 'iron', 'gold', 'diamond',
|
|
'wheat', 'carrot', 'potato', 'apple',
|
|
'sword', 'pickaxe', 'axe', 'hoe',
|
|
'health_potion', 'mana_potion'
|
|
];
|
|
|
|
for (const item of items) {
|
|
this.createHighResIcon(item);
|
|
}
|
|
|
|
console.log(`🖼️ Generated ${items.length} high-res icons (64x64)`);
|
|
}
|
|
|
|
createHighResIcon(itemName) {
|
|
const graphics = this.scene.add.graphics();
|
|
const size = this.iconSize;
|
|
|
|
// Icon background
|
|
graphics.fillStyle(0x333333, 1);
|
|
graphics.fillRoundedRect(0, 0, size, size, 8);
|
|
|
|
// Icon border
|
|
graphics.lineStyle(2, 0x666666, 1);
|
|
graphics.strokeRoundedRect(0, 0, size, size, 8);
|
|
|
|
// Item-specific graphics
|
|
switch (itemName) {
|
|
case 'wood':
|
|
graphics.fillStyle(0x8B4513, 1);
|
|
graphics.fillRect(16, 16, 32, 32);
|
|
break;
|
|
case 'stone':
|
|
graphics.fillStyle(0x808080, 1);
|
|
graphics.fillCircle(32, 32, 16);
|
|
break;
|
|
case 'gold':
|
|
graphics.fillStyle(0xFFD700, 1);
|
|
graphics.fillCircle(32, 32, 16);
|
|
break;
|
|
case 'diamond':
|
|
graphics.fillStyle(0x00FFFF, 1);
|
|
graphics.fillTriangle(32, 16, 16, 48, 48, 48);
|
|
break;
|
|
case 'sword':
|
|
graphics.fillStyle(0xC0C0C0, 1);
|
|
graphics.fillRect(28, 16, 8, 32);
|
|
graphics.fillTriangle(32, 16, 24, 24, 40, 24);
|
|
break;
|
|
case 'health_potion':
|
|
graphics.fillStyle(0xFF0000, 1);
|
|
graphics.fillCircle(32, 32, 16);
|
|
graphics.fillStyle(0xFFFFFF, 0.5);
|
|
graphics.fillCircle(28, 28, 4);
|
|
break;
|
|
default:
|
|
graphics.fillStyle(0x666666, 1);
|
|
graphics.fillRect(20, 20, 24, 24);
|
|
}
|
|
|
|
// Generate texture
|
|
graphics.generateTexture(`icon_${itemName}_64`, size, size);
|
|
graphics.destroy();
|
|
|
|
this.iconCache.set(itemName, `icon_${itemName}_64`);
|
|
}
|
|
|
|
getIcon(itemName) {
|
|
return this.iconCache.get(itemName) || 'icon_default_64';
|
|
}
|
|
|
|
// ========== ANIMATED UI ELEMENTS ==========
|
|
|
|
addPulsingElement(element, minScale = 0.95, maxScale = 1.05, duration = 1000) {
|
|
if (!this.settings.animatedUI) return;
|
|
|
|
const tween = this.scene.tweens.add({
|
|
targets: element,
|
|
scale: { from: minScale, to: maxScale },
|
|
duration: duration,
|
|
yoyo: true,
|
|
repeat: -1,
|
|
ease: 'Sine.easeInOut'
|
|
});
|
|
|
|
this.pulsingElements.push({ element, tween });
|
|
return tween;
|
|
}
|
|
|
|
addGlowingElement(element, color = 0xffff00, intensity = 0.5) {
|
|
if (!this.settings.animatedUI) return;
|
|
|
|
// Create glow effect
|
|
const glow = this.scene.add.circle(
|
|
element.x,
|
|
element.y,
|
|
element.width * 0.6,
|
|
color,
|
|
intensity
|
|
);
|
|
glow.setBlendMode(Phaser.BlendModes.ADD);
|
|
glow.setDepth(element.depth - 1);
|
|
|
|
// Pulsing glow
|
|
this.scene.tweens.add({
|
|
targets: glow,
|
|
alpha: { from: intensity, to: 0 },
|
|
scale: { from: 1, to: 1.5 },
|
|
duration: 1500,
|
|
yoyo: true,
|
|
repeat: -1
|
|
});
|
|
|
|
this.glowingElements.push({ element, glow });
|
|
return glow;
|
|
}
|
|
|
|
addHoverEffect(element, callback) {
|
|
if (!this.settings.animatedUI) return;
|
|
|
|
element.setInteractive();
|
|
|
|
element.on('pointerover', () => {
|
|
this.scene.tweens.add({
|
|
targets: element,
|
|
scale: 1.1,
|
|
duration: 200,
|
|
ease: 'Back.easeOut'
|
|
});
|
|
if (callback) callback('over');
|
|
});
|
|
|
|
element.on('pointerout', () => {
|
|
this.scene.tweens.add({
|
|
targets: element,
|
|
scale: 1.0,
|
|
duration: 200,
|
|
ease: 'Back.easeIn'
|
|
});
|
|
if (callback) callback('out');
|
|
});
|
|
|
|
element.on('pointerdown', () => {
|
|
this.scene.tweens.add({
|
|
targets: element,
|
|
scale: 0.95,
|
|
duration: 100
|
|
});
|
|
if (callback) callback('down');
|
|
});
|
|
|
|
element.on('pointerup', () => {
|
|
this.scene.tweens.add({
|
|
targets: element,
|
|
scale: 1.1,
|
|
duration: 100
|
|
});
|
|
if (callback) callback('up');
|
|
});
|
|
}
|
|
|
|
// ========== CUSTOM CURSORS ==========
|
|
|
|
setupCustomCursors() {
|
|
// Create custom cursor sprites
|
|
this.createCursorSprites();
|
|
}
|
|
|
|
createCursorSprites() {
|
|
// Sword cursor
|
|
const sword = this.scene.add.graphics();
|
|
sword.fillStyle(0xC0C0C0, 1);
|
|
sword.fillRect(0, 0, 4, 16);
|
|
sword.fillTriangle(2, 0, 0, 4, 4, 4);
|
|
sword.generateTexture('cursor_sword', 16, 16);
|
|
sword.destroy();
|
|
|
|
// Pickaxe cursor
|
|
const pickaxe = this.scene.add.graphics();
|
|
pickaxe.fillStyle(0x8B4513, 1);
|
|
pickaxe.fillRect(6, 8, 4, 8);
|
|
pickaxe.fillStyle(0x808080, 1);
|
|
pickaxe.fillRect(0, 0, 12, 8);
|
|
pickaxe.generateTexture('cursor_pickaxe', 16, 16);
|
|
pickaxe.destroy();
|
|
|
|
console.log('🖱️ Custom cursors created');
|
|
}
|
|
|
|
setCursor(cursorType) {
|
|
if (!this.settings.customCursors) return;
|
|
|
|
this.currentCursor = cursorType;
|
|
|
|
if (this.cursors[cursorType]) {
|
|
document.body.style.cursor = this.cursors[cursorType];
|
|
}
|
|
}
|
|
|
|
resetCursor() {
|
|
this.setCursor('default');
|
|
}
|
|
|
|
// ========== LOADING SCREEN ==========
|
|
|
|
showLoadingScreen(text = 'Loading...') {
|
|
if (!this.settings.loadingArtwork) return;
|
|
|
|
// Create loading screen container
|
|
this.loadingScreen = this.scene.add.container(0, 0);
|
|
this.loadingScreen.setDepth(10000);
|
|
this.loadingScreen.setScrollFactor(0);
|
|
|
|
const width = this.scene.cameras.main.width;
|
|
const height = this.scene.cameras.main.height;
|
|
|
|
// Background
|
|
const bg = this.scene.add.rectangle(
|
|
width / 2,
|
|
height / 2,
|
|
width,
|
|
height,
|
|
0x000000,
|
|
0.9
|
|
);
|
|
this.loadingScreen.add(bg);
|
|
|
|
// Logo/Title
|
|
const title = this.scene.add.text(
|
|
width / 2,
|
|
height / 2 - 100,
|
|
'Mrtva Dolina',
|
|
{
|
|
fontSize: '64px',
|
|
fontFamily: 'Arial',
|
|
color: '#00ff00',
|
|
fontStyle: 'bold'
|
|
}
|
|
);
|
|
title.setOrigin(0.5);
|
|
this.loadingScreen.add(title);
|
|
|
|
// Loading text
|
|
const loadingText = this.scene.add.text(
|
|
width / 2,
|
|
height / 2,
|
|
text,
|
|
{
|
|
fontSize: '24px',
|
|
fontFamily: 'Arial',
|
|
color: '#ffffff'
|
|
}
|
|
);
|
|
loadingText.setOrigin(0.5);
|
|
this.loadingScreen.add(loadingText);
|
|
|
|
// Progress bar background
|
|
const barBg = this.scene.add.rectangle(
|
|
width / 2,
|
|
height / 2 + 50,
|
|
400,
|
|
30,
|
|
0x333333
|
|
);
|
|
this.loadingScreen.add(barBg);
|
|
|
|
// Progress bar fill
|
|
const barFill = this.scene.add.rectangle(
|
|
width / 2 - 200,
|
|
height / 2 + 50,
|
|
0,
|
|
30,
|
|
0x00ff00
|
|
);
|
|
barFill.setOrigin(0, 0.5);
|
|
this.loadingScreen.add(barFill);
|
|
this.loadingScreen.barFill = barFill;
|
|
|
|
// Pulsing animation
|
|
this.scene.tweens.add({
|
|
targets: loadingText,
|
|
alpha: { from: 1, to: 0.5 },
|
|
duration: 800,
|
|
yoyo: true,
|
|
repeat: -1
|
|
});
|
|
}
|
|
|
|
updateLoadingProgress(progress) {
|
|
if (!this.loadingScreen || !this.loadingScreen.barFill) return;
|
|
|
|
this.loadingProgress = Phaser.Math.Clamp(progress, 0, 100);
|
|
|
|
this.scene.tweens.add({
|
|
targets: this.loadingScreen.barFill,
|
|
width: (this.loadingProgress / 100) * 400,
|
|
duration: 300,
|
|
ease: 'Power2'
|
|
});
|
|
}
|
|
|
|
hideLoadingScreen() {
|
|
if (!this.loadingScreen) return;
|
|
|
|
this.scene.tweens.add({
|
|
targets: this.loadingScreen,
|
|
alpha: 0,
|
|
duration: 500,
|
|
onComplete: () => {
|
|
this.loadingScreen.destroy();
|
|
this.loadingScreen = null;
|
|
}
|
|
});
|
|
}
|
|
|
|
// ========== ACHIEVEMENTS ==========
|
|
|
|
initAchievements() {
|
|
// Define achievements
|
|
this.defineAchievement('first_harvest', {
|
|
name: 'First Harvest',
|
|
description: 'Harvest your first crop',
|
|
icon: '🌾',
|
|
points: 10
|
|
});
|
|
|
|
this.defineAchievement('master_farmer', {
|
|
name: 'Master Farmer',
|
|
description: 'Harvest 1000 crops',
|
|
icon: '👨🌾',
|
|
points: 50
|
|
});
|
|
|
|
this.defineAchievement('explorer', {
|
|
name: 'Explorer',
|
|
description: 'Explore 50% of the map',
|
|
icon: '🗺️',
|
|
points: 25
|
|
});
|
|
|
|
this.defineAchievement('rich', {
|
|
name: 'Wealthy',
|
|
description: 'Accumulate 10,000 gold',
|
|
icon: '💰',
|
|
points: 30
|
|
});
|
|
|
|
// Load unlocked achievements
|
|
this.loadUnlockedAchievements();
|
|
}
|
|
|
|
defineAchievement(id, data) {
|
|
this.achievements.set(id, {
|
|
id,
|
|
...data,
|
|
unlocked: false,
|
|
unlockedAt: null
|
|
});
|
|
}
|
|
|
|
unlockAchievement(id) {
|
|
const achievement = this.achievements.get(id);
|
|
if (!achievement || achievement.unlocked) return;
|
|
|
|
achievement.unlocked = true;
|
|
achievement.unlockedAt = Date.now();
|
|
this.unlockedAchievements.add(id);
|
|
|
|
// Show notification
|
|
if (this.settings.achievementNotifications) {
|
|
this.showAchievementNotification(achievement);
|
|
}
|
|
|
|
// Save
|
|
this.saveUnlockedAchievements();
|
|
|
|
console.log(`🏆 Achievement unlocked: ${achievement.name}`);
|
|
}
|
|
|
|
showAchievementNotification(achievement) {
|
|
const width = this.scene.cameras.main.width;
|
|
|
|
// Create notification
|
|
const notification = this.scene.add.container(width + 300, 100);
|
|
notification.setDepth(10001);
|
|
notification.setScrollFactor(0);
|
|
|
|
// Background
|
|
const bg = this.scene.add.rectangle(0, 0, 300, 100, 0x000000, 0.9);
|
|
bg.setStrokeStyle(2, 0xFFD700);
|
|
notification.add(bg);
|
|
|
|
// Icon
|
|
const icon = this.scene.add.text(-120, 0, achievement.icon, {
|
|
fontSize: '48px'
|
|
});
|
|
icon.setOrigin(0.5);
|
|
notification.add(icon);
|
|
|
|
// Text
|
|
const title = this.scene.add.text(-50, -20, 'Achievement Unlocked!', {
|
|
fontSize: '16px',
|
|
color: '#FFD700',
|
|
fontStyle: 'bold'
|
|
});
|
|
title.setOrigin(0, 0.5);
|
|
notification.add(title);
|
|
|
|
const name = this.scene.add.text(-50, 5, achievement.name, {
|
|
fontSize: '20px',
|
|
color: '#ffffff',
|
|
fontStyle: 'bold'
|
|
});
|
|
name.setOrigin(0, 0.5);
|
|
notification.add(name);
|
|
|
|
const points = this.scene.add.text(-50, 25, `+${achievement.points} points`, {
|
|
fontSize: '14px',
|
|
color: '#00ff00'
|
|
});
|
|
points.setOrigin(0, 0.5);
|
|
notification.add(points);
|
|
|
|
// Slide in
|
|
this.scene.tweens.add({
|
|
targets: notification,
|
|
x: width - 170,
|
|
duration: 500,
|
|
ease: 'Back.easeOut',
|
|
onComplete: () => {
|
|
// Wait, then slide out
|
|
this.scene.time.delayedCall(3000, () => {
|
|
this.scene.tweens.add({
|
|
targets: notification,
|
|
x: width + 300,
|
|
duration: 500,
|
|
ease: 'Back.easeIn',
|
|
onComplete: () => notification.destroy()
|
|
});
|
|
});
|
|
}
|
|
});
|
|
|
|
// Sparkle effect
|
|
if (this.scene.visualEnhancements) {
|
|
this.scene.visualEnhancements.createSparkleEffect(
|
|
notification.x,
|
|
notification.y
|
|
);
|
|
}
|
|
}
|
|
|
|
getAchievementProgress() {
|
|
const total = this.achievements.size;
|
|
const unlocked = this.unlockedAchievements.size;
|
|
return {
|
|
total,
|
|
unlocked,
|
|
percentage: (unlocked / total) * 100
|
|
};
|
|
}
|
|
|
|
// ========== PERSISTENCE ==========
|
|
|
|
saveUnlockedAchievements() {
|
|
const data = Array.from(this.unlockedAchievements);
|
|
localStorage.setItem('novafarma_achievements', JSON.stringify(data));
|
|
}
|
|
|
|
loadUnlockedAchievements() {
|
|
const saved = localStorage.getItem('novafarma_achievements');
|
|
if (saved) {
|
|
const data = JSON.parse(saved);
|
|
this.unlockedAchievements = new Set(data);
|
|
|
|
// Mark achievements as unlocked
|
|
for (const id of this.unlockedAchievements) {
|
|
const achievement = this.achievements.get(id);
|
|
if (achievement) {
|
|
achievement.unlocked = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
saveSettings() {
|
|
localStorage.setItem('novafarma_ui_graphics', JSON.stringify(this.settings));
|
|
}
|
|
|
|
loadSettings() {
|
|
const saved = localStorage.getItem('novafarma_ui_graphics');
|
|
if (saved) {
|
|
this.settings = { ...this.settings, ...JSON.parse(saved) };
|
|
}
|
|
}
|
|
|
|
destroy() {
|
|
this.saveUnlockedAchievements();
|
|
console.log('🎨 UI Graphics System destroyed');
|
|
}
|
|
}
|