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
This commit is contained in:
265
src/ui/WeatherUI.js
Normal file
265
src/ui/WeatherUI.js
Normal file
@@ -0,0 +1,265 @@
|
||||
/**
|
||||
* 🌦️ 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user