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:
380
src/ui/CraftingUI.js
Normal file
380
src/ui/CraftingUI.js
Normal file
@@ -0,0 +1,380 @@
|
||||
// Crafting UI - Visual panel for crafting interface
|
||||
class CraftingUI {
|
||||
constructor(scene) {
|
||||
this.scene = scene;
|
||||
this.craftingSystem = scene.craftingSystem;
|
||||
|
||||
this.isOpen = false;
|
||||
this.currentCategory = 'all';
|
||||
this.selectedRecipe = null;
|
||||
|
||||
// UI elements
|
||||
this.container = null;
|
||||
this.panel = null;
|
||||
this.categoryButtons = [];
|
||||
this.recipeList = [];
|
||||
this.detailsPanel = null;
|
||||
|
||||
this.createUI();
|
||||
this.hide();
|
||||
|
||||
// Listen for crafting events
|
||||
this.setupEventListeners();
|
||||
|
||||
console.log('🎨 CraftingUI initialized');
|
||||
}
|
||||
|
||||
createUI() {
|
||||
const width = this.scene.cameras.main.width;
|
||||
const height = this.scene.cameras.main.height;
|
||||
|
||||
// Main container
|
||||
this.container = this.scene.add.container(0, 0);
|
||||
this.container.setDepth(10000);
|
||||
this.container.setScrollFactor(0);
|
||||
|
||||
// Semi-transparent background overlay
|
||||
const overlay = this.scene.add.rectangle(0, 0, width, height, 0x000000, 0.7);
|
||||
overlay.setOrigin(0);
|
||||
overlay.setInteractive();
|
||||
this.container.add(overlay);
|
||||
|
||||
// Main panel (centered)
|
||||
const panelWidth = 700;
|
||||
const panelHeight = 500;
|
||||
const panelX = width / 2 - panelWidth / 2;
|
||||
const panelY = height / 2 - panelHeight / 2;
|
||||
|
||||
this.panel = this.scene.add.rectangle(panelX, panelY, panelWidth, panelHeight, 0x2a1810);
|
||||
this.panel.setOrigin(0);
|
||||
this.panel.setStrokeStyle(3, 0x4a3820);
|
||||
this.container.add(this.panel);
|
||||
|
||||
// Title
|
||||
const title = this.scene.add.text(width / 2, panelY + 20, '🛠️ CRAFTING', {
|
||||
fontSize: '32px',
|
||||
fontFamily: 'Georgia, serif',
|
||||
fill: '#f4e4c1',
|
||||
stroke: '#2d1b00',
|
||||
strokeThickness: 4
|
||||
}).setOrigin(0.5);
|
||||
this.container.add(title);
|
||||
|
||||
// Close button
|
||||
const closeBtn = this.scene.add.text(panelX + panelWidth - 40, panelY + 20, '✖', {
|
||||
fontSize: '24px',
|
||||
fill: '#ff6666'
|
||||
}).setOrigin(0.5);
|
||||
closeBtn.setInteractive({ useHandCursor: true });
|
||||
closeBtn.on('pointerdown', () => this.hide());
|
||||
closeBtn.on('pointerover', () => closeBtn.setScale(1.2));
|
||||
closeBtn.on('pointerout', () => closeBtn.setScale(1.0));
|
||||
this.container.add(closeBtn);
|
||||
|
||||
// Category buttons (top)
|
||||
this.createCategoryButtons(panelX, panelY + 60, panelWidth);
|
||||
|
||||
// Recipe list (left side)
|
||||
this.createRecipeListPanel(panelX + 10, panelY + 120, 300, 350);
|
||||
|
||||
// Details panel (right side)
|
||||
this.createDetailsPanel(panelX + 320, panelY + 120, 370, 350);
|
||||
}
|
||||
|
||||
createCategoryButtons(x, y, width) {
|
||||
const categories = this.craftingSystem.categories;
|
||||
const buttonWidth = (width - 40) / categories.length;
|
||||
|
||||
categories.forEach((category, index) => {
|
||||
const btnX = x + 20 + (index * buttonWidth);
|
||||
|
||||
const btn = this.scene.add.rectangle(btnX, y, buttonWidth - 10, 40, 0x4a3820);
|
||||
btn.setOrigin(0, 0.5);
|
||||
btn.setStrokeStyle(2, 0x6a5840);
|
||||
btn.setInteractive({ useHandCursor: true });
|
||||
|
||||
const text = this.scene.add.text(btnX + buttonWidth / 2 - 5, y, `${category.icon} ${category.name}`, {
|
||||
fontSize: '14px',
|
||||
fontFamily: 'Arial',
|
||||
fill: '#d4c4a1'
|
||||
}).setOrigin(0.5);
|
||||
|
||||
btn.on('pointerdown', () => this.selectCategory(category.id));
|
||||
btn.on('pointerover', () => {
|
||||
btn.setFillStyle(0x6a5840);
|
||||
text.setScale(1.05);
|
||||
});
|
||||
btn.on('pointerout', () => {
|
||||
btn.setFillStyle(0x4a3820);
|
||||
text.setScale(1.0);
|
||||
});
|
||||
|
||||
this.container.add(btn);
|
||||
this.container.add(text);
|
||||
|
||||
this.categoryButtons.push({ category: category.id, btn, text });
|
||||
});
|
||||
}
|
||||
|
||||
createRecipeListPanel(x, y, width, height) {
|
||||
// Background
|
||||
const bg = this.scene.add.rectangle(x, y, width, height, 0x1a1410);
|
||||
bg.setOrigin(0);
|
||||
bg.setStrokeStyle(2, 0x4a3820);
|
||||
this.container.add(bg);
|
||||
|
||||
// Title
|
||||
const title = this.scene.add.text(x + width / 2, y + 10, 'Recipes', {
|
||||
fontSize: '18px',
|
||||
fontFamily: 'Georgia, serif',
|
||||
fill: '#f4e4c1'
|
||||
}).setOrigin(0.5, 0);
|
||||
this.container.add(title);
|
||||
|
||||
// Store panel bounds for recipe items
|
||||
this.recipePanelBounds = { x, y: y + 40, width, height: height - 40 };
|
||||
}
|
||||
|
||||
createDetailsPanel(x, y, width, height) {
|
||||
// Background
|
||||
const bg = this.scene.add.rectangle(x, y, width, height, 0x1a1410);
|
||||
bg.setOrigin(0);
|
||||
bg.setStrokeStyle(2, 0x4a3820);
|
||||
this.container.add(bg);
|
||||
|
||||
this.detailsPanelBounds = { x, y, width, height };
|
||||
}
|
||||
|
||||
selectCategory(categoryId) {
|
||||
this.currentCategory = categoryId;
|
||||
this.refreshRecipeList();
|
||||
|
||||
// Update button styles
|
||||
this.categoryButtons.forEach(({ category, btn, text }) => {
|
||||
if (category === categoryId) {
|
||||
btn.setFillStyle(0x6a5840);
|
||||
text.setStyle({ fill: '#ffffff' });
|
||||
} else {
|
||||
btn.setFillStyle(0x4a3820);
|
||||
text.setStyle({ fill: '#d4c4a1' });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
refreshRecipeList() {
|
||||
// Clear existing recipe items
|
||||
this.recipeList.forEach(item => item.destroy());
|
||||
this.recipeList = [];
|
||||
|
||||
// Get recipes for current category
|
||||
const recipes = this.craftingSystem.getUnlockedRecipes(this.currentCategory);
|
||||
|
||||
const { x, y, width } = this.recipePanelBounds;
|
||||
const itemHeight = 50;
|
||||
|
||||
recipes.forEach((recipe, index) => {
|
||||
const itemY = y + (index * itemHeight);
|
||||
|
||||
// Check if can craft
|
||||
const canCraft = this.craftingSystem.canCraft(recipe.id);
|
||||
|
||||
// Background
|
||||
const bg = this.scene.add.rectangle(x + 5, itemY, width - 10, itemHeight - 5, 0x2a1810);
|
||||
bg.setOrigin(0);
|
||||
bg.setStrokeStyle(1, canCraft.canCraft ? 0x4a9d5f : 0x6a5840);
|
||||
bg.setInteractive({ useHandCursor: true });
|
||||
|
||||
// Recipe name
|
||||
const name = this.scene.add.text(x + 15, itemY + itemHeight / 2, recipe.name, {
|
||||
fontSize: '16px',
|
||||
fontFamily: 'Arial',
|
||||
fill: canCraft.canCraft ? '#ffffff' : '#888888'
|
||||
}).setOrigin(0, 0.5);
|
||||
|
||||
// Hover effect
|
||||
bg.on('pointerover', () => {
|
||||
bg.setFillStyle(0x3a2820);
|
||||
name.setScale(1.05);
|
||||
});
|
||||
bg.on('pointerout', () => {
|
||||
bg.setFillStyle(0x2a1810);
|
||||
name.setScale(1.0);
|
||||
});
|
||||
|
||||
// Click to select
|
||||
bg.on('pointerdown', () => this.selectRecipe(recipe));
|
||||
|
||||
this.container.add(bg);
|
||||
this.container.add(name);
|
||||
|
||||
this.recipeList.push(bg, name);
|
||||
});
|
||||
}
|
||||
|
||||
selectRecipe(recipe) {
|
||||
this.selectedRecipe = recipe;
|
||||
this.showRecipeDetails();
|
||||
}
|
||||
|
||||
showRecipeDetails() {
|
||||
if (!this.selectedRecipe) return;
|
||||
|
||||
// Clear existing details
|
||||
if (this.detailsContent) {
|
||||
this.detailsContent.forEach(item => item.destroy());
|
||||
}
|
||||
this.detailsContent = [];
|
||||
|
||||
const { x, y, width } = this.detailsPanelBounds;
|
||||
const recipe = this.selectedRecipe;
|
||||
|
||||
// Recipe name
|
||||
const name = this.scene.add.text(x + width / 2, y + 20, recipe.name, {
|
||||
fontSize: '24px',
|
||||
fontFamily: 'Georgia, serif',
|
||||
fill: '#f4e4c1',
|
||||
stroke: '#2d1b00',
|
||||
strokeThickness: 2
|
||||
}).setOrigin(0.5, 0);
|
||||
this.detailsContent.push(name);
|
||||
|
||||
// Description
|
||||
const desc = this.scene.add.text(x + 20, y + 60, recipe.description, {
|
||||
fontSize: '14px',
|
||||
fontFamily: 'Arial',
|
||||
fill: '#d4c4a1',
|
||||
wordWrap: { width: width - 40 }
|
||||
});
|
||||
this.detailsContent.push(desc);
|
||||
|
||||
// Ingredients title
|
||||
const ingredTitle = this.scene.add.text(x + 20, y + 120, 'Required Ingredients:', {
|
||||
fontSize: '16px',
|
||||
fontFamily: 'Arial',
|
||||
fill: '#f4e4c1',
|
||||
fontStyle: 'bold'
|
||||
});
|
||||
this.detailsContent.push(ingredTitle);
|
||||
|
||||
// Ingredients list
|
||||
const inventory = this.scene.inventorySystem;
|
||||
let ingredY = y + 150;
|
||||
|
||||
for (const [itemId, required] of Object.entries(recipe.ingredients)) {
|
||||
const has = inventory ? inventory.getItemCount(itemId) : 0;
|
||||
const hasEnough = has >= required;
|
||||
|
||||
const text = this.scene.add.text(x + 30, ingredY, `• ${itemId}: ${has}/${required}`, {
|
||||
fontSize: '14px',
|
||||
fontFamily: 'Arial',
|
||||
fill: hasEnough ? '#4a9d5f' : '#ff6666'
|
||||
});
|
||||
this.detailsContent.push(text);
|
||||
ingredY += 25;
|
||||
}
|
||||
|
||||
// Result
|
||||
const resultText = this.scene.add.text(x + 20, ingredY + 20, `Produces: ${recipe.result.quantity}x ${recipe.result.item}`, {
|
||||
fontSize: '16px',
|
||||
fontFamily: 'Arial',
|
||||
fill: '#4aa3d0',
|
||||
fontStyle: 'bold'
|
||||
});
|
||||
this.detailsContent.push(resultText);
|
||||
|
||||
// Craft button
|
||||
const canCraft = this.craftingSystem.canCraft(recipe.id);
|
||||
const btnY = y + 320;
|
||||
|
||||
const craftBtn = this.scene.add.rectangle(x + width / 2, btnY, 200, 40, canCraft.canCraft ? 0x4a9d5f : 0x666666);
|
||||
craftBtn.setStrokeStyle(2, 0x000000);
|
||||
|
||||
const btnText = this.scene.add.text(x + width / 2, btnY, canCraft.canCraft ? '🔨 CRAFT' : '❌ Cannot Craft', {
|
||||
fontSize: '18px',
|
||||
fontFamily: 'Arial',
|
||||
fill: '#ffffff',
|
||||
fontStyle: 'bold'
|
||||
}).setOrigin(0.5);
|
||||
|
||||
if (canCraft.canCraft) {
|
||||
craftBtn.setInteractive({ useHandCursor: true });
|
||||
craftBtn.on('pointerover', () => {
|
||||
craftBtn.setFillStyle(0x5abd6f);
|
||||
btnText.setScale(1.1);
|
||||
});
|
||||
craftBtn.on('pointerout', () => {
|
||||
craftBtn.setFillStyle(0x4a9d5f);
|
||||
btnText.setScale(1.0);
|
||||
});
|
||||
craftBtn.on('pointerdown', () => this.craftSelectedRecipe());
|
||||
}
|
||||
|
||||
this.detailsContent.push(craftBtn, btnText);
|
||||
|
||||
// Add all to container
|
||||
this.detailsContent.forEach(item => this.container.add(item));
|
||||
}
|
||||
|
||||
craftSelectedRecipe() {
|
||||
if (!this.selectedRecipe) return;
|
||||
|
||||
const success = this.craftingSystem.craftItem(this.selectedRecipe.id);
|
||||
|
||||
if (success) {
|
||||
// Refresh UI
|
||||
this.refreshRecipeList();
|
||||
this.showRecipeDetails();
|
||||
|
||||
console.log(`✅ Crafting started: ${this.selectedRecipe.name}`);
|
||||
}
|
||||
}
|
||||
|
||||
setupEventListeners() {
|
||||
// Listen for inventory changes to update recipe availability
|
||||
this.scene.events.on('inventory-changed', () => {
|
||||
if (this.isOpen) {
|
||||
this.refreshRecipeList();
|
||||
if (this.selectedRecipe) {
|
||||
this.showRecipeDetails();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Listen for craft completion
|
||||
this.scene.events.on('craft-complete', (data) => {
|
||||
if (this.isOpen) {
|
||||
this.refreshRecipeList();
|
||||
if (this.selectedRecipe) {
|
||||
this.showRecipeDetails();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
show() {
|
||||
this.isOpen = true;
|
||||
this.container.setVisible(true);
|
||||
this.selectCategory(this.currentCategory);
|
||||
console.log('🛠️ Crafting UI opened');
|
||||
}
|
||||
|
||||
hide() {
|
||||
this.isOpen = false;
|
||||
this.container.setVisible(false);
|
||||
console.log('🛠️ Crafting UI closed');
|
||||
}
|
||||
|
||||
toggle() {
|
||||
if (this.isOpen) {
|
||||
this.hide();
|
||||
} else {
|
||||
this.show();
|
||||
}
|
||||
}
|
||||
|
||||
destroy() {
|
||||
if (this.container) {
|
||||
this.container.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
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