/** * SettingsScene.js * Settings screen with sound, music, and vibration toggles. */ const { SCREEN_WIDTH, SCREEN_HEIGHT, COLORS, SCENE, } = require('../base/GameGlobal'); const { t } = require('../i18n/I18n'); const SettingsScene = { _settings: { soundEnabled: true, musicEnabled: true, vibrationEnabled: true, }, _buttons: {}, enter() { // Load settings from storage try { const saved = wx.getStorageSync('game_settings'); if (saved) { this._settings = { ...this._settings, ...JSON.parse(saved) }; } } catch (e) { console.warn('[Settings] Failed to load settings:', e); } this._buttons = {}; }, exit() { // Save settings try { wx.setStorageSync('game_settings', JSON.stringify(this._settings)); } catch (e) { console.warn('[Settings] Failed to save settings:', e); } }, update(dt) {}, render(ctx) { // Background ctx.fillStyle = COLORS.MENU_BG; ctx.fillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); const cx = SCREEN_WIDTH / 2; let y = 60; // Title ctx.fillStyle = COLORS.MENU_TITLE; ctx.font = 'bold 28px Arial'; ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; ctx.fillText(t('settings.title'), cx, y); y += 70; // Toggle items const toggles = [ { key: 'soundEnabled', label: t('settings.sound'), icon: '🔊' }, { key: 'musicEnabled', label: t('settings.music'), icon: '🎵' }, { key: 'vibrationEnabled', label: t('settings.vibration'), icon: '📳' }, ]; for (const toggle of toggles) { this._renderToggle(ctx, cx, y, toggle); y += 70; } // Back button y = SCREEN_HEIGHT - 80; this._renderBackButton(ctx, cx, y); }, _renderToggle(ctx, cx, y, toggle) { const w = SCREEN_WIDTH * 0.7; const h = 50; const x = cx - w / 2; const isOn = this._settings[toggle.key]; // Store button rect this._buttons[toggle.key] = { x, y: y - h / 2, w, h }; // Background ctx.fillStyle = '#1e1e3a'; ctx.fillRect(x, y - h / 2, w, h); ctx.strokeStyle = '#333366'; ctx.lineWidth = 1; ctx.strokeRect(x, y - h / 2, w, h); // Icon and label ctx.fillStyle = COLORS.HUD_TEXT; ctx.font = '16px Arial'; ctx.textAlign = 'left'; ctx.textBaseline = 'middle'; ctx.fillText(`${toggle.icon} ${toggle.label}`, x + 15, y); // Toggle switch const switchW = 50; const switchH = 26; const switchX = x + w - switchW - 15; const switchY = y - switchH / 2; // Switch track ctx.fillStyle = isOn ? '#4CAF50' : '#555555'; ctx.beginPath(); ctx.arc(switchX + switchH / 2, y, switchH / 2, Math.PI / 2, Math.PI * 3 / 2); ctx.arc(switchX + switchW - switchH / 2, y, switchH / 2, -Math.PI / 2, Math.PI / 2); ctx.closePath(); ctx.fill(); // Switch knob ctx.fillStyle = '#FFFFFF'; ctx.beginPath(); const knobX = isOn ? switchX + switchW - switchH / 2 : switchX + switchH / 2; ctx.arc(knobX, y, switchH / 2 - 3, 0, Math.PI * 2); ctx.fill(); }, _renderBackButton(ctx, cx, y) { const w = SCREEN_WIDTH * 0.4; const h = 42; const x = cx - w / 2; this._buttons['back'] = { x, y: y - h / 2, w, h }; ctx.fillStyle = COLORS.MENU_BTN; ctx.strokeStyle = COLORS.MENU_BTN_BORDER; ctx.lineWidth = 2; ctx.fillRect(x, y - h / 2, w, h); ctx.strokeRect(x, y - h / 2, w, h); ctx.fillStyle = COLORS.MENU_BTN_TEXT; ctx.font = 'bold 16px Arial'; ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; ctx.fillText(t('common.back'), cx, y); }, handleTouch(eventType, e) { if (eventType !== 'touchstart') return; const touch = e.touches[0]; const tx = touch.clientX; const ty = touch.clientY; for (const [key, rect] of Object.entries(this._buttons)) { if (tx >= rect.x && tx <= rect.x + rect.w && ty >= rect.y && ty <= rect.y + rect.h) { if (key === 'back') { GameGlobal.sceneManager.switchTo(SCENE.MENU); } else if (this._settings.hasOwnProperty(key)) { this._settings[key] = !this._settings[key]; // Notify audio system GameGlobal.eventBus.emit('settings:changed', this._settings); } break; } } }, }; module.exports = SettingsScene;