Files
tankwar_proj/js/scenes/SettingsScene.js

181 lines
5.0 KiB
JavaScript

/**
* 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;
// Reset button map each frame so layout changes don't keep stale rects.
this._buttons = {};
// Title
const titleY = Math.max(48, SCREEN_HEIGHT * 0.08);
ctx.fillStyle = COLORS.MENU_TITLE;
ctx.font = 'bold 28px Arial';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText(t('settings.title'), cx, titleY);
// Back button (reserved at bottom so we can layout rows above it).
const backH = 42;
const backMarginBottom = 28;
const backCenterY = SCREEN_HEIGHT - backMarginBottom - backH / 2;
// Rows: nickname + 3 toggles. Distribute evenly between title and back btn.
const rows = [
{ type: 'toggle', key: 'soundEnabled', label: t('settings.sound'), icon: '🔊' },
{ type: 'toggle', key: 'musicEnabled', label: t('settings.music'), icon: '🎵' },
{ type: 'toggle', key: 'vibrationEnabled', label: t('settings.vibration'), icon: '📳' },
];
const rowH = 50;
const topPad = titleY + 36;
const bottomPad = backCenterY - backH / 2 - 20;
const availH = Math.max(rowH * rows.length, bottomPad - topPad);
const step = Math.max(rowH + 8, availH / rows.length);
const firstCenterY = topPad + step / 2;
for (let i = 0; i < rows.length; i++) {
const row = rows[i];
const cy = firstCenterY + i * step;
this._renderToggle(ctx, cx, cy, row);
}
// Back button
this._renderBackButton(ctx, cx, backCenterY);
},
_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;