Files
game-forest/src/app/SettingsScreen.ts
T
2026-09-09 19:52:27 +03:00

85 lines
3.2 KiB
TypeScript

import { getRenderSettings, setRenderSettings } from '../pixi/renderSettings';
/** Builds a toggle button that shows its current on/off state in its own label and flips it on
* click — the DOM-side equivalent of a checkbox, styled like the rest of the menu's buttons. */
function createToggle(label: string, initial: boolean, onChange: (value: boolean) => void): HTMLButtonElement {
const btn = document.createElement('button');
btn.type = 'button';
btn.className = 'menu-btn';
let value = initial;
function render(): void {
btn.textContent = `${label}: ${value ? 'вкл' : 'выкл'}`;
}
render();
btn.addEventListener('click', () => {
value = !value;
render();
onChange(value);
});
return btn;
}
/** Builds the settings screen — rendering-diagnostics toggles that take effect the next time a
* game is (re)started (GameCanvas reads them once, on mount), plus a seed field, reachable from
* the main menu.
* @param currentSeed The running game's current PRNG seed (see GameStore.seed) — 0 if no game has
* started yet this page load. Shown as the seed field's starting value.
* @param onStartWithSeed Called with a new seed the instant the seed field's value is committed
* (blur or Enter) — starts (or restarts) a game seeded from it, discarding any existing save, the
* same way "Новая игра" does. */
export function createSettingsScreen(currentSeed: number, onBack: () => void, onStartWithSeed: (seed: number) => void): HTMLElement {
const root = document.createElement('div');
root.className = 'main-menu';
const title = document.createElement('h1');
title.className = 'main-menu__title';
title.textContent = 'Настройки';
const buttons = document.createElement('div');
buttons.className = 'main-menu__buttons';
const settings = getRenderSettings();
const antialiasingBtn = createToggle('Антиалиасинг экрана', settings.antialiasing, (value) => {
setRenderSettings({ antialiasing: value });
});
const noScaleBtn = createToggle('Рендер без масштабирования (k=1)', settings.noScale, (value) => {
setRenderSettings({ noScale: value });
});
const seedLabel = document.createElement('label');
seedLabel.className = 'settings-seed-label';
seedLabel.textContent = 'Сид игры (новая игра при изменении)';
const seedInput = document.createElement('input');
seedInput.type = 'number';
seedInput.className = 'settings-seed-input';
seedInput.min = '0';
seedInput.max = '4294967295';
seedInput.step = '1';
seedInput.value = String(currentSeed);
seedInput.addEventListener('change', () => {
const parsed = Math.floor(Number(seedInput.value));
if (!Number.isFinite(parsed) || parsed < 0) {
seedInput.value = String(currentSeed);
return;
}
onStartWithSeed(parsed >>> 0);
});
seedLabel.appendChild(seedInput);
const backBtn = document.createElement('button');
backBtn.type = 'button';
backBtn.className = 'menu-btn';
backBtn.textContent = 'Назад';
backBtn.addEventListener('click', onBack);
buttons.append(antialiasingBtn, noScaleBtn, seedLabel, backBtn);
root.append(title, buttons);
return root;
}