Files
novafarma/src/ui/WeatherUI.js
NovaFarma Dev 80bddf5d61 feat: Complete 2D Visual Overhaul - Isometric to Flat Top-Down
- NEW: Flat2DTerrainSystem.js (375 lines)
- NEW: map2d_data.js procedural map (221 lines)
- MODIFIED: GameScene async create, 2D terrain integration
- MODIFIED: Player.js flat 2D positioning
- MODIFIED: game.js disabled pixelArt for smooth rendering
- FIXED: 15+ bugs (updateCulling, isometric conversions, grid lines)
- ADDED: Phase 28 to TASKS.md
- DOCS: DNEVNIK.md session summary

Result: Working flat 2D game with Stardew Valley style!
Time: 5.5 hours
2025-12-14 17:12:40 +01:00

266 lines
7.6 KiB
JavaScript

/**
* 🌦️ WEATHER CONTROL UI PANEL
* Separate UI for weather system controls
*/
class WeatherUI {
constructor(scene) {
this.scene = scene;
this.container = null;
this.isVisible = false;
this.createPanel();
this.hide(); // Start hidden
// Toggle with W key
this.scene.input.keyboard.on('keydown-W', () => {
this.toggle();
});
}
createPanel() {
const width = 300;
const height = 400;
const x = 20;
const y = 100;
// Main container
this.container = this.scene.add.container(x, y);
this.container.setDepth(900000); // High depth (below debug UI)
this.container.setScrollFactor(0);
// Background
const bg = this.scene.add.rectangle(0, 0, width, height, 0x222222, 0.9);
bg.setOrigin(0, 0);
bg.setStrokeStyle(2, 0x44aaff);
this.container.add(bg);
// Title
const title = this.scene.add.text(width / 2, 20, '🌦️ WEATHER CONTROL', {
fontSize: '20px',
fontFamily: 'Arial',
fontStyle: 'bold',
fill: '#44aaff'
});
title.setOrigin(0.5, 0);
this.container.add(title);
// Current Weather Display
const currentLabel = this.scene.add.text(20, 60, 'Current:', {
fontSize: '16px',
fill: '#ffffff'
});
this.container.add(currentLabel);
this.currentWeatherText = this.scene.add.text(width - 20, 60, 'Clear ☀️', {
fontSize: '16px',
fontStyle: 'bold',
fill: '#ffdd00'
});
this.currentWeatherText.setOrigin(1, 0);
this.container.add(this.currentWeatherText);
// Intensity Display
const intensityLabel = this.scene.add.text(20, 90, 'Intensity:', {
fontSize: '16px',
fill: '#ffffff'
});
this.container.add(intensityLabel);
this.intensityText = this.scene.add.text(width - 20, 90, '100%', {
fontSize: '16px',
fontStyle: 'bold',
fill: '#00ff88'
});
this.intensityText.setOrigin(1, 0);
this.container.add(this.intensityText);
// Intensity Slider Visual
const sliderBg = this.scene.add.rectangle(20, 120, width - 40, 10, 0x444444);
sliderBg.setOrigin(0, 0);
this.container.add(sliderBg);
this.intensityBar = this.scene.add.rectangle(20, 120, (width - 40) * 1.0, 10, 0x00ff88);
this.intensityBar.setOrigin(0, 0);
this.container.add(this.intensityBar);
// Auto Cycle Status
const autoLabel = this.scene.add.text(20, 150, 'Auto Cycle:', {
fontSize: '16px',
fill: '#ffffff'
});
this.container.add(autoLabel);
this.autoText = this.scene.add.text(width - 20, 150, 'OFF', {
fontSize: '16px',
fontStyle: 'bold',
fill: '#ff4444'
});
this.autoText.setOrigin(1, 0);
this.container.add(this.autoText);
// Weather Buttons
const buttonY = 190;
const buttonData = [
{ label: '☀️ Clear', weather: 'clear', color: 0xffdd00 },
{ label: '🌧️ Rain', weather: 'rain', color: 0x44aaff },
{ label: '❄️ Snow', weather: 'snow', color: 0xccccff },
{ label: '⚡ Storm', weather: 'storm', color: 0xff4444 },
{ label: '🌫️ Fog', weather: 'fog', color: 0x888888 }
];
buttonData.forEach((data, index) => {
const btn = this.createButton(
width / 2,
buttonY + (index * 35),
width - 40,
30,
data.label,
data.color,
() => this.scene.setWeather(data.weather)
);
this.container.add(btn);
});
// Controls Help
const helpY = buttonY + (buttonData.length * 35) + 10;
const help = this.scene.add.text(width / 2, helpY,
'CONTROLS:\n' +
'W = Toggle Panel\n' +
'Shift+A = Auto Cycle\n' +
'+/- = Intensity', {
fontSize: '12px',
fill: '#888888',
align: 'center'
});
help.setOrigin(0.5, 0);
this.container.add(help);
}
createButton(x, y, width, height, text, color, onClick) {
const container = this.scene.add.container(x, y);
const bg = this.scene.add.rectangle(0, 0, width, height, color, 0.8);
bg.setStrokeStyle(2, 0xffffff, 0.5);
bg.setInteractive({ useHandCursor: true });
const label = this.scene.add.text(0, 0, text, {
fontSize: '14px',
fontFamily: 'Arial',
fontStyle: 'bold',
fill: '#ffffff'
});
label.setOrigin(0.5, 0.5);
bg.on('pointerover', () => {
bg.setAlpha(1.0);
bg.setStrokeStyle(2, 0xffffff, 1.0);
});
bg.on('pointerout', () => {
bg.setAlpha(0.8);
bg.setStrokeStyle(2, 0xffffff, 0.5);
});
bg.on('pointerdown', () => {
this.scene.tweens.add({
targets: container,
scaleX: 0.95,
scaleY: 0.95,
duration: 100,
yoyo: true
});
onClick();
});
container.add(bg);
container.add(label);
return container;
}
update() {
if (!this.isVisible) return;
// Update current weather display
const weatherIcons = {
clear: '☀️',
rain: '🌧️',
snow: '❄️',
storm: '⚡',
fog: '🌫️'
};
const weatherColors = {
clear: '#ffdd00',
rain: '#44aaff',
snow: '#ccccff',
storm: '#ff4444',
fog: '#888888'
};
const currentWeather = this.scene.currentWeather || 'clear';
const icon = weatherIcons[currentWeather] || '☀️';
const color = weatherColors[currentWeather] || '#ffdd00';
this.currentWeatherText.setText(`${currentWeather.charAt(0).toUpperCase() + currentWeather.slice(1)} ${icon}`);
this.currentWeatherText.setColor(color);
// Update intensity
const intensity = this.scene.weatherIntensity || 1.0;
this.intensityText.setText(`${Math.round(intensity * 100)}%`);
this.intensityBar.setScale((intensity / 2.0), 1); // Max 2.0 = 100% width
// Update auto cycle status
const autoEnabled = this.scene.autoWeatherEnabled || false;
this.autoText.setText(autoEnabled ? 'ON' : 'OFF');
this.autoText.setColor(autoEnabled ? '#00ff88' : '#ff4444');
}
toggle() {
if (this.isVisible) {
this.hide();
} else {
this.show();
}
}
show() {
this.isVisible = true;
this.container.setVisible(true);
// Slide in animation
this.container.setAlpha(0);
this.container.x = -320;
this.scene.tweens.add({
targets: this.container,
x: 20,
alpha: 1,
duration: 300,
ease: 'Back.easeOut'
});
}
hide() {
this.isVisible = false;
// Slide out animation
this.scene.tweens.add({
targets: this.container,
x: -320,
alpha: 0,
duration: 300,
ease: 'Back.easeIn',
onComplete: () => {
this.container.setVisible(false);
}
});
}
destroy() {
if (this.container) {
this.container.destroy();
}
}
}