Documentation

Ui Components

Π’ этом Ρ€Π°Π·Π΄Π΅Π»Π΅ ΠΎΠΏΠΈΡΡ‹Π²Π°ΡŽΡ‚ΡΡ Π³ΠΎΡ‚ΠΎΠ²Ρ‹Π΅ UI ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ для быстрого создания Π²Π΅Π±-интСрфСйсов Π² Wudgine.

Π’Π²Π΅Π΄Π΅Π½ΠΈΠ΅

Wudgine прСдоставляСт Π½Π°Π±ΠΎΡ€ Π³ΠΎΡ‚ΠΎΠ²Ρ‹Ρ… UI ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ², ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΏΠΎΠΌΠΎΠ³ΡƒΡ‚ Π²Π°ΠΌ быстро ΡΠΎΠ·Π΄Π°Π²Π°Ρ‚ΡŒ ΠΏΡ€ΠΎΡ„Π΅ΡΡΠΈΠΎΠ½Π°Π»ΡŒΠ½Ρ‹Π΅ ΠΈΠ³Ρ€ΠΎΠ²Ρ‹Π΅ интСрфСйсы. Π­Ρ‚ΠΈ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½Ρ‹ для Ρ€Π°Π±ΠΎΡ‚Ρ‹ с Π΄Π²ΠΈΠΆΠΊΠΎΠΌ ΠΈ ΡΠ»Π΅Π΄ΡƒΡŽΡ‚ Π»ΡƒΡ‡ΡˆΠΈΠΌ ΠΏΡ€Π°ΠΊΡ‚ΠΈΠΊΠ°ΠΌ Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ ΠΈΠ³Ρ€ΠΎΠ²Ρ‹Ρ… UI.

Π‘Π°Π·ΠΎΠ²Ρ‹Π΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹

Кнопки

<button class="wg-button wg-button-primary">ΠΠ°Ρ‡Π°Ρ‚ΡŒ ΠΈΠ³Ρ€Ρƒ</button>
<button class="wg-button wg-button-secondary">Настройки</button>
<button class="wg-button wg-button-danger">Π’Ρ‹Ρ…ΠΎΠ΄</button>

ДоступныС классы для ΠΊΠ½ΠΎΠΏΠΎΠΊ:

  • wg-button-primary - основная ΠΊΠ½ΠΎΠΏΠΊΠ°
  • wg-button-secondary - второстСпСнная ΠΊΠ½ΠΎΠΏΠΊΠ°
  • wg-button-danger - ΠΊΠ½ΠΎΠΏΠΊΠ° для опасных дСйствий
  • wg-button-small - малСнькая ΠΊΠ½ΠΎΠΏΠΊΠ°
  • wg-button-large - большая ΠΊΠ½ΠΎΠΏΠΊΠ°
  • wg-button-disabled - ΠΎΡ‚ΠΊΠ»ΡŽΡ‡Π΅Π½Π½Π°Ρ ΠΊΠ½ΠΎΠΏΠΊΠ°

ПанСли

<div class="wg-panel">
  <div class="wg-panel-header">Π—Π°Π³ΠΎΠ»ΠΎΠ²ΠΎΠΊ ΠΏΠ°Π½Π΅Π»ΠΈ</div>
  <div class="wg-panel-body">
    Π‘ΠΎΠ΄Π΅Ρ€ΠΆΠΈΠΌΠΎΠ΅ ΠΏΠ°Π½Π΅Π»ΠΈ
  </div>
  <div class="wg-panel-footer">
    <button class="wg-button wg-button-primary">OK</button>
    <button class="wg-button wg-button-secondary">ΠžΡ‚ΠΌΠ΅Π½Π°</button>
  </div>
</div>

Π˜Π½Π΄ΠΈΠΊΠ°Ρ‚ΠΎΡ€Ρ‹ прогрСсса

<!-- ΠŸΡ€ΠΎΡΡ‚ΠΎΠΉ прогрСсс-Π±Π°Ρ€ -->
<div class="wg-progress">
  <div class="wg-progress-bar" style="width: 75%"></div>
</div>

<!-- ΠŸΡ€ΠΎΠ³Ρ€Π΅ΡΡ-Π±Π°Ρ€ с тСкстом -->
<div class="wg-progress">
  <div class="wg-progress-bar" style="width: 75%">75%</div>
</div>

<!-- ΠŸΡ€ΠΎΠ³Ρ€Π΅ΡΡ-Π±Π°Ρ€ с двумя значСниями (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Π·Π΄ΠΎΡ€ΠΎΠ²ΡŒΠ΅/ΠΌΠ°Π½Π°) -->
<div class="wg-progress wg-progress-dual">
  <div class="wg-progress-bar wg-progress-primary" style="width: 60%"></div>
  <div class="wg-progress-bar wg-progress-secondary" style="width: 40%"></div>
</div>

Π‘Π»ΠΎΡ‚Ρ‹ инвСнтаря

<div class="wg-inventory-grid">
  <div class="wg-inventory-slot">
    <div class="wg-item" data-item-id="sword_01">
      <img src="items/sword.png" alt="ΠœΠ΅Ρ‡">
      <span class="wg-item-count">1</span>
    </div>
  </div>
  <div class="wg-inventory-slot"></div>
  <div class="wg-inventory-slot">
    <div class="wg-item" data-item-id="potion_health">
      <img src="items/health_potion.png" alt="Π—Π΅Π»ΡŒΠ΅ Π·Π΄ΠΎΡ€ΠΎΠ²ΡŒΡ">
      <span class="wg-item-count">5</span>
    </div>
  </div>
  <!-- Π”ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ слоты -->
</div>

Π”ΠΈΠ°Π»ΠΎΠ³ΠΎΠ²Ρ‹Π΅ ΠΎΠΊΠ½Π°

<div class="wg-dialog" id="confirmDialog">
  <div class="wg-dialog-content">
    <div class="wg-dialog-header">
      <h3>ΠŸΠΎΠ΄Ρ‚Π²Π΅Ρ€ΠΆΠ΄Π΅Π½ΠΈΠ΅</h3>
      <button class="wg-dialog-close">&times;</button>
    </div>
    <div class="wg-dialog-body">
      <p>Π’Ρ‹ ΡƒΠ²Π΅Ρ€Π΅Π½Ρ‹, Ρ‡Ρ‚ΠΎ Ρ…ΠΎΡ‚ΠΈΡ‚Π΅ ΠΏΡ€ΠΎΠ΄ΠΎΠ»ΠΆΠΈΡ‚ΡŒ?</p>
    </div>
    <div class="wg-dialog-footer">
      <button class="wg-button wg-button-primary" id="confirmYes">Π”Π°</button>
      <button class="wg-button wg-button-secondary" id="confirmNo">НСт</button>
    </div>
  </div>
</div>
// ΠŸΠΎΠΊΠ°Π·Π°Ρ‚ΡŒ Π΄ΠΈΠ°Π»ΠΎΠ³
document.getElementById('confirmDialog').classList.add('wg-dialog-visible');

// Π‘ΠΊΡ€Ρ‹Ρ‚ΡŒ Π΄ΠΈΠ°Π»ΠΎΠ³
document.getElementById('confirmDialog').classList.remove('wg-dialog-visible');

Π’ΡΠΏΠ»Ρ‹Π²Π°ΡŽΡ‰ΠΈΠ΅ подсказки

<div class="wg-tooltip-container">
  <button class="wg-button wg-button-primary">Навык</button>
  <div class="wg-tooltip">
    <h4>ΠžΠ³Π½Π΅Π½Π½Ρ‹ΠΉ ΡˆΠ°Ρ€</h4>
    <p>Наносит 50-75 ΡƒΡ€ΠΎΠ½Π° ΠΎΠ³Π½Π΅ΠΌ</p>
    <p class="wg-tooltip-cooldown">ΠŸΠ΅Ρ€Π΅Π·Π°Ρ€ΡΠ΄ΠΊΠ°: 30 сСк</p>
  </div>
</div>

HUD ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹

ΠœΠΈΠ½ΠΈΠΊΠ°Ρ€Ρ‚Π°

<div class="wg-minimap">
  <div class="wg-minimap-container">
    <!-- Π—Π΄Π΅ΡΡŒ Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ°Ρ‚ΡŒΡΡ ΠΊΠ°Ρ€Ρ‚Π° -->
  </div>
  <div class="wg-minimap-controls">
    <button class="wg-minimap-zoom-in">+</button>
    <button class="wg-minimap-zoom-out">-</button>
  </div>
</div>
class Minimap {
  constructor(options = {}) {
    this.container = document.querySelector(options.container || '.wg-minimap-container');
    this.scale = options.initialScale || 1.0;
    this.playerMarker = null;
    this.markers = new Map();
    
    this.initialize();
  }
  
  initialize() {
    // Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ ΠΌΠ°Ρ€ΠΊΠ΅Ρ€Π° ΠΈΠ³Ρ€ΠΎΠΊΠ°
    this.playerMarker = document.createElement('div');
    this.playerMarker.className = 'wg-minimap-player-marker';
    this.container.appendChild(this.playerMarker);
    
    // Подписка Π½Π° ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΠ΅ ΠΏΠΎΠ·ΠΈΡ†ΠΈΠΈ ΠΈΠ³Ρ€ΠΎΠΊΠ°
    engine.subscribe('playerPositionChanged', (data) => {
      this.updatePlayerPosition(data.x, data.y);
    });
    
    // Настройка элСмСнтов управлСния
    document.querySelector('.wg-minimap-zoom-in').addEventListener('click', () => {
      this.setScale(this.scale + 0.1);
    });
    
    document.querySelector('.wg-minimap-zoom-out').addEventListener('click', () => {
      this.setScale(this.scale - 0.1);
    });
  }
  
  updatePlayerPosition(x, y) {
    // ΠŸΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ ΠΊΠΎΠΎΡ€Π΄ΠΈΠ½Π°Ρ‚ ΠΈΠ³Ρ€ΠΎΠ²ΠΎΠ³ΠΎ ΠΌΠΈΡ€Π° Π² ΠΊΠΎΠΎΡ€Π΄ΠΈΠ½Π°Ρ‚Ρ‹ ΠΌΠΈΠ½ΠΈΠΊΠ°Ρ€Ρ‚Ρ‹
    const mapX = x * this.scale;
    const mapY = y * this.scale;
    
    this.playerMarker.style.transform = `translate(${mapX}px, ${mapY}px)`;
  }
  
  setScale(newScale) {
    // ΠžΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΠ΅ ΠΌΠ°ΡΡˆΡ‚Π°Π±Π°
    this.scale = Math.max(0.5, Math.min(2.0, newScale));
    
    // ОбновлСниС отобраТСния
    this.container.style.transform = `scale(${this.scale})`;
  }
  
  addMarker(id, x, y, type = 'default') {
    // Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ ΠΌΠ°Ρ€ΠΊΠ΅Ρ€Π° Π½Π° ΠΊΠ°Ρ€Ρ‚Π΅
    const marker = document.createElement('div');
    marker.className = `wg-minimap-marker wg-minimap-marker-${type}`;
    marker.style.transform = `translate(${x * this.scale}px, ${y * this.scale}px)`;
    
    this.container.appendChild(marker);
    this.markers.set(id, marker);
    
    return marker;
  }
  
  removeMarker(id) {
    const marker = this.markers.get(id);
    if (marker) {
      marker.remove();
      this.markers.delete(id);
    }
  }
}

Π˜Π½Π΄ΠΈΠΊΠ°Ρ‚ΠΎΡ€Ρ‹ Π·Π΄ΠΎΡ€ΠΎΠ²ΡŒΡ ΠΈ рСсурсов

<div class="wg-player-stats">
  <div class="wg-stat-container">
    <div class="wg-stat-label">Π—Π΄ΠΎΡ€ΠΎΠ²ΡŒΠ΅</div>
    <div class="wg-progress">
      <div class="wg-progress-bar wg-health-bar" style="width: 75%">750/1000</div>
    </div>
  </div>
  
  <div class="wg-stat-container">
    <div class="wg-stat-label">Мана</div>
    <div class="wg-progress">
      <div class="wg-progress-bar wg-mana-bar" style="width: 50%">250/500</div>
    </div>
  </div>
  
  <div class="wg-stat-container">
    <div class="wg-stat-label">Π’Ρ‹Π½ΠΎΡΠ»ΠΈΠ²ΠΎΡΡ‚ΡŒ</div>
    <div class="wg-progress">
      <div class="wg-progress-bar wg-stamina-bar" style="width: 90%">90/100</div>
    </div>
  </div>
</div>
class PlayerStatsUI {
  constructor() {
    this.healthBar = document.querySelector('.wg-health-bar');
    this.manaBar = document.querySelector('.wg-mana-bar');
    this.staminaBar = document.querySelector('.wg-stamina-bar');
    
    this.initialize();
  }
  
  initialize() {
    // Подписка Π½Π° события измСнСния характСристик ΠΈΠ³Ρ€ΠΎΠΊΠ°
    engine.subscribe('playerStatsChanged', (data) => {
      this.updateStats(data);
    });
    
    // ΠΠ°Ρ‡Π°Π»ΡŒΠ½ΠΎΠ΅ ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΠ΅
    this.updateStats(engine.call('getPlayerStats'));
  }
  
  updateStats(stats) {
    // ОбновлСниС полосы Π·Π΄ΠΎΡ€ΠΎΠ²ΡŒΡ
    const healthPercent = (stats.currentHealth / stats.maxHealth) * 100;
    this.healthBar.style.width = `${healthPercent}%`;
    this.healthBar.textContent = `${stats.currentHealth}/${stats.maxHealth}`;
    
    // ИзмСнСниС Ρ†Π²Π΅Ρ‚Π° ΠΏΡ€ΠΈ Π½ΠΈΠ·ΠΊΠΎΠΌ Π·Π΄ΠΎΡ€ΠΎΠ²ΡŒΠ΅
    if (healthPercent < 25) {
      this.healthBar.classList.add('wg-critical');
    } else {
      this.healthBar.classList.remove('wg-critical');
    }
    
    // ОбновлСниС полосы ΠΌΠ°Π½Ρ‹
    const manaPercent = (stats.currentMana / stats.maxMana) * 100;
    this.manaBar.style.width = `${manaPercent}%`;
    this.manaBar.textContent = `${stats.currentMana}/${stats.maxMana}`;
    
    // ОбновлСниС полосы выносливости
    const staminaPercent = (stats.currentStamina / stats.maxStamina) * 100;
    this.staminaBar.style.width = `${staminaPercent}%`;
    this.staminaBar.textContent = `${stats.currentStamina}/${stats.maxStamina}`;
  }
}

ПанСль дСйствий

<div class="wg-action-bar">
  <div class="wg-action-slot" data-slot="1">
    <img src="skills/fireball.png" alt="ΠžΠ³Π½Π΅Π½Π½Ρ‹ΠΉ ΡˆΠ°Ρ€">
    <span class="wg-action-keybind">1</span>
    <div class="wg-action-cooldown" style="height: 30%"></div>
  </div>
  <div class="wg-action-slot" data-slot="2">
    <img src="skills/heal.png" alt="Π˜ΡΡ†Π΅Π»Π΅Π½ΠΈΠ΅">
    <span class="wg-action-keybind">2</span>
  </div>
  <!-- Π”ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ слоты -->
</div>
class ActionBar {
  constructor() {
    this.slots = document.querySelectorAll('.wg-action-slot');
    this.cooldowns = new Map();
    
    this.initialize();
  }
  
  initialize() {
    // Подписка Π½Π° события измСнСния способностСй
    engine.subscribe('abilityCooldownChanged', (data) => {
      this.updateCooldown(data.slotIndex, data.remainingCooldown, data.totalCooldown);
    });
    
    // ΠžΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° Π½Π°ΠΆΠ°Ρ‚ΠΈΠΉ Π½Π° слоты
    this.slots.forEach(slot => {
      slot.addEventListener('click', () => {
        const slotIndex = parseInt(slot.dataset.slot);
        this.activateAbility(slotIndex);
      });
    });
    
    // ΠžΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° Π½Π°ΠΆΠ°Ρ‚ΠΈΠΉ клавиш
    document.addEventListener('keydown', (e) => {
      // ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ°, являСтся Π»ΠΈ наТатая клавиша Ρ†ΠΈΡ„Ρ€ΠΎΠΉ ΠΎΡ‚ 1 Π΄ΠΎ 9
      if (e.key >= '1' && e.key <= '9') {
        const slotIndex = parseInt(e.key);
        this.activateAbility(slotIndex);
      }
    });
  }
  
  activateAbility(slotIndex) {
    // ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ°, Π½Π΅ Π½Π° пСрСзарядкС Π»ΠΈ ΡΠΏΠΎΡΠΎΠ±Π½ΠΎΡΡ‚ΡŒ
    if (this.cooldowns.has(slotIndex)) {
      return;
    }
    
    // Π’Ρ‹Π·ΠΎΠ² способности Ρ‡Π΅Ρ€Π΅Π· Π΄Π²ΠΈΠΆΠΎΠΊ
    const result = engine.call('activateAbility', { slotIndex });
    
    if (result.success) {
      // Если ΡΠΏΠΎΡΠΎΠ±Π½ΠΎΡΡ‚ΡŒ ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎ Π°ΠΊΡ‚ΠΈΠ²ΠΈΡ€ΠΎΠ²Π°Π½Π°, Π½Π°Ρ‡ΠΈΠ½Π°Π΅ΠΌ отсчСт пСрСзарядки
      if (result.cooldown > 0) {
        this.updateCooldown(slotIndex, result.cooldown, result.cooldown);
      }
    }
  }
  
  updateCooldown(slotIndex, remainingCooldown, totalCooldown) {
    const slot = document.querySelector(`.wg-action-slot[data-slot="${slotIndex}"]`);
    if (!slot) return;
    
    const cooldownOverlay = slot.querySelector('.wg-action-cooldown');
    
    if (remainingCooldown <= 0) {
      // ΠŸΠ΅Ρ€Π΅Π·Π°Ρ€ΡΠ΄ΠΊΠ° Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½Π°
      cooldownOverlay.style.height = '0%';
      this.cooldowns.delete(slotIndex);
    } else {
      // ОбновлСниС ΠΈΠ½Π΄ΠΈΠΊΠ°Ρ‚ΠΎΡ€Π° пСрСзарядки
      const percent = (remainingCooldown / totalCooldown) * 100;
      cooldownOverlay.style.height = `${percent}%`;
      
      // Π‘ΠΎΡ…Ρ€Π°Π½Π΅Π½ΠΈΠ΅ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΈ ΠΎ пСрСзарядкС
      this.cooldowns.set(slotIndex, {
        remaining: remainingCooldown,
        total: totalCooldown
      });
      
      // УмСньшСниС ΠΎΡΡ‚Π°Π²ΡˆΠ΅Π³ΠΎΡΡ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ
      setTimeout(() => {
        this.updateCooldown(slotIndex, remainingCooldown - 0.1, totalCooldown);
      }, 100);
    }
  }
}

МСню ΠΈ экраны

Π“Π»Π°Π²Π½ΠΎΠ΅ мСню

<div class="wg-main-menu">
  <div class="wg-menu-logo">
    <img src="logo.png" alt="НазваниС ΠΈΠ³Ρ€Ρ‹">
  </div>
  
  <div class="wg-menu-buttons">
    <button class="wg-button wg-button-primary wg-button-large" id="btnPlay">Π˜Π³Ρ€Π°Ρ‚ΡŒ</button>
    <button class="wg-button wg-button-primary wg-button-large" id="btnContinue">ΠŸΡ€ΠΎΠ΄ΠΎΠ»ΠΆΠΈΡ‚ΡŒ</button>
    <button class="wg-button wg-button-secondary wg-button-large" id="btnSettings">Настройки</button>
    <button class="wg-button wg-button-secondary wg-button-large" id="btnCredits">Авторы</button>
    <button class="wg-button wg-button-danger wg-button-large" id="btnExit">Π’Ρ‹Ρ…ΠΎΠ΄</button>
  </div>
  
  <div class="wg-menu-footer">
    <p>ВСрсия 1.0.0</p>
    <p>&copy; 2023 Wudgine Studios</p>
  </div>
</div>
class MainMenu {
  constructor() {
    this.initialize();
  }
  
  initialize() {
    // ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° наличия сохранСний
    const hasSaveGame = engine.call('checkSaveGame');
    
    // ΠŸΠΎΠΊΠ°Π·Π°Ρ‚ΡŒ/ΡΠΊΡ€Ρ‹Ρ‚ΡŒ ΠΊΠ½ΠΎΠΏΠΊΡƒ "ΠŸΡ€ΠΎΠ΄ΠΎΠ»ΠΆΠΈΡ‚ΡŒ"
    const continueButton = document.getElementById('btnContinue');
    continueButton.style.display = hasSaveGame ? 'block' : 'none';
    
    // Настройка ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΎΠ² событий
    document.getElementById('btnPlay').addEventListener('click', () => {
      engine.call('startNewGame');
    });
    
    document.getElementById('btnContinue').addEventListener('click', () => {
      engine.call('loadGame');
    });
    
    document.getElementById('btnSettings').addEventListener('click', () => {
      engine.call('showSettings');
    });
    
    document.getElementById('btnCredits').addEventListener('click', () => {
      engine.call('showCredits');
    });
    
    document.getElementById('btnExit').addEventListener('click', () => {
      engine.call('exitGame');
    });
  }
}

Π­ΠΊΡ€Π°Π½ настроСк

<div class="wg-settings-screen">
  <div class="wg-panel">
    <div class="wg-panel-header">
      <h2>Настройки</h2>
      <button class="wg-panel-close" id="btnCloseSettings">&times;</button>
    </div>
    
    <div class="wg-panel-body">
      <div class="wg-tabs">
        <div class="wg-tab-buttons">
          <button class="wg-tab-button active" data-tab="graphics">Π“Ρ€Π°Ρ„ΠΈΠΊΠ°</button>
          <button class="wg-tab-button" data-tab="audio">Π—Π²ΡƒΠΊ</button>
          <button class="wg-tab-button" data-tab="controls">Π£ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅</button>
          <button class="wg-tab-button" data-tab="gameplay">Π“Π΅ΠΉΠΌΠΏΠ»Π΅ΠΉ</button>
        </div>
        
        <div class="wg-tab-content">
          <div class="wg-tab-pane active" id="graphics">
            <!-- Настройки Π³Ρ€Π°Ρ„ΠΈΠΊΠΈ -->
            <div class="wg-setting-row">
              <label for="resolution">Π Π°Π·Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅:</label>
              <select id="resolution" class="wg-select">
                <option value="1920x1080">1920x1080</option>
                <option value="1280x720">1280x720</option>
                <!-- Π”Ρ€ΡƒΠ³ΠΈΠ΅ Π²Π°Ρ€ΠΈΠ°Π½Ρ‚Ρ‹ -->
              </select>
            </div>
            
            <div class="wg-setting-row">
              <label for="quality">ΠšΠ°Ρ‡Π΅ΡΡ‚Π²ΠΎ Π³Ρ€Π°Ρ„ΠΈΠΊΠΈ:</label>
              <select id="quality" class="wg-select">
                <option value="low">НизкоС</option>
                <option value="medium">Π‘Ρ€Π΅Π΄Π½Π΅Π΅</option>
                <option value="high">ВысокоС</option>
                <option value="ultra">Π£Π»ΡŒΡ‚Ρ€Π°</option>
              </select>
            </div>
            
            <div class="wg-setting-row">
              <label for="fullscreen">ΠŸΠΎΠ»Π½ΠΎΡΠΊΡ€Π°Π½Π½Ρ‹ΠΉ Ρ€Π΅ΠΆΠΈΠΌ:</label>
              <input type="checkbox" id="fullscreen" class="wg-checkbox">
            </div>
          </div>
          
          <!-- Π”Ρ€ΡƒΠ³ΠΈΠ΅ Π²ΠΊΠ»Π°Π΄ΠΊΠΈ настроСк -->
        </div>
      </div>
    </div>
    
    <div class="wg-panel-footer">
      <button class="wg-button wg-button-primary" id="btnSaveSettings">Π‘ΠΎΡ…Ρ€Π°Π½ΠΈΡ‚ΡŒ</button>
      <button class="wg-button wg-button-secondary" id="btnResetSettings">Π‘Π±Ρ€ΠΎΡΠΈΡ‚ΡŒ</button>
    </div>
  </div>
</div>
class SettingsScreen {
  constructor() {
    this.currentSettings = {};
    this.initialize();
  }
  
  async initialize() {
    // Π—Π°Π³Ρ€ΡƒΠ·ΠΊΠ° Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΡ… настроСк
    this.currentSettings = await engine.call('getSettings');
    
    // Π—Π°ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ ΠΏΠΎΠ»Π΅ΠΉ Ρ„ΠΎΡ€ΠΌΡ‹
    this.populateForm();
    
    // Настройка ΠΏΠ΅Ρ€Π΅ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ Π²ΠΊΠ»Π°Π΄ΠΎΠΊ
    const tabButtons = document.querySelectorAll('.wg-tab-button');
    tabButtons.forEach(button => {
      button.addEventListener('click', () => {
        // Π£Π΄Π°Π»Π΅Π½ΠΈΠ΅ Π°ΠΊΡ‚ΠΈΠ²Π½ΠΎΠ³ΠΎ класса Ρƒ всСх ΠΊΠ½ΠΎΠΏΠΎΠΊ ΠΈ ΠΏΠ°Π½Π΅Π»Π΅ΠΉ
        document.querySelectorAll('.wg-tab-button').forEach(btn => {
          btn.classList.remove('active');
        });
        document.querySelectorAll('.wg-tab-pane').forEach(pane => {
          pane.classList.remove('active');
        });
        
        // Активация Π²Ρ‹Π±Ρ€Π°Π½Π½ΠΎΠΉ Π²ΠΊΠ»Π°Π΄ΠΊΠΈ
        button.classList.add('active');
        const tabId = button.dataset.tab;
        document.getElementById(tabId).classList.add('active');
      });
    });
    
    // ΠžΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ ΠΊΠ½ΠΎΠΏΠΎΠΊ
    document.getElementById('btnCloseSettings').addEventListener('click', () => {
      engine.call('hideSettings');
    });
    
    document.getElementById('btnSaveSettings').addEventListener('click', () => {
      this.saveSettings();
    });
    
    document.getElementById('btnResetSettings').addEventListener('click', () => {
      this.resetSettings();
    });
  }
  
  populateForm() {
    // Π—Π°ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ ΠΏΠΎΠ»Π΅ΠΉ Ρ„ΠΎΡ€ΠΌΡ‹ Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΌΠΈ настройками
    document.getElementById('resolution').value = this.currentSettings.resolution;
    document.getElementById('quality').value = this.currentSettings.quality;
    document.getElementById('fullscreen').checked = this.currentSettings.fullscreen;
    
    // Π—Π°ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ Π΄Ρ€ΡƒΠ³ΠΈΡ… настроСк
    // ...
  }
  
  async saveSettings() {
    // Π‘Π±ΠΎΡ€ Π΄Π°Π½Π½Ρ‹Ρ… ΠΈΠ· Ρ„ΠΎΡ€ΠΌΡ‹
    const newSettings = {
      resolution: document.getElementById('resolution').value,
      quality: document.getElementById('quality').value,
      fullscreen: document.getElementById('fullscreen').checked,
      // Π”Ρ€ΡƒΠ³ΠΈΠ΅ настройки
    };
    
    // Π‘ΠΎΡ…Ρ€Π°Π½Π΅Π½ΠΈΠ΅ настроСк
    const result = await engine.call('saveSettings', newSettings);
    
    if (result.success) {
      // ΠŸΠΎΠΊΠ°Π·Π°Ρ‚ΡŒ ΡƒΠ²Π΅Π΄ΠΎΠΌΠ»Π΅Π½ΠΈΠ΅ ΠΎΠ± ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎΠΌ сохранСнии
      this.showNotification('Настройки ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎ сохранСны');
      
      // ОбновлСниС Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΡ… настроСк
      this.currentSettings = newSettings;
    } else {
      // ΠŸΠΎΠΊΠ°Π·Π°Ρ‚ΡŒ ΠΎΡˆΠΈΠ±ΠΊΡƒ
      this.showNotification('Ошибка ΠΏΡ€ΠΈ сохранСнии настроСк', 'error');
    }
  }
  
  async resetSettings() {
    // Бброс настроСк ΠΊ значСниям ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ
    const defaultSettings = await engine.call('getDefaultSettings');
    
    // ОбновлСниС Ρ„ΠΎΡ€ΠΌΡ‹
    this.currentSettings = defaultSettings;
    this.populateForm();
    
    // ΠŸΠΎΠΊΠ°Π·Π°Ρ‚ΡŒ ΡƒΠ²Π΅Π΄ΠΎΠΌΠ»Π΅Π½ΠΈΠ΅
    this.showNotification('Настройки ΡΠ±Ρ€ΠΎΡˆΠ΅Π½Ρ‹ ΠΊ значСниям ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ');
  }
  
  showNotification(message, type = 'success') {
    // Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ элСмСнта увСдомлСния
    const notification = document.createElement('div');
    notification.className = `wg-notification wg-notification-${type}`;
    notification.textContent = message;
    
    // Π”ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ Π½Π° страницу
    document.body.appendChild(notification);
    
    // Π£Π΄Π°Π»Π΅Π½ΠΈΠ΅ Ρ‡Π΅Ρ€Π΅Π· 3 сСкунды
    setTimeout(() => {
      notification.classList.add('wg-notification-hide');
      setTimeout(() => {
        notification.remove();
      }, 300);
    }, 3000);
  }
}

Wudgine β€’ Β© 2025