diff --git a/php/index.php b/php/index.php
index f65558c..e3cc610 100644
--- a/php/index.php
+++ b/php/index.php
@@ -13,6 +13,8 @@
canvas { border: 3px solid #e94560; border-radius: 12px; box-shadow: 0 0 20px rgba(233,69,96,0.4); }
#hud { display: flex; gap: 20px; color: #e94560; font-size: 16px; font-weight: bold; }
#hud span { background: rgba(233,69,96,0.1); padding: 8px 16px; border-radius: 20px; border: 1px solid rgba(233,69,96,0.3); }
+ #menu-btn { cursor: pointer; }
+ #menu-btn:hover { background: rgba(233,69,96,0.25) !important; }
#controls { color: #aaa; font-size: 13px; }
kbd { background: #1a1a2e; border: 1px solid #e94560; border-radius: 4px; padding: 2px 6px; color: #e94560; }
#solve-overlay { position: fixed; inset: 0; background: rgba(10,10,21,0.75); display: flex; justify-content: center; align-items: center; z-index: 10; }
@@ -124,6 +126,7 @@
Уровень 1
📦 0/0
👣 0
+
← → ↑ ↓ или WASD — движение
@@ -131,7 +134,8 @@
P — пред.
R — рестарт
F — автопоиск (Esc — отмена)
- G — лучшее сохранённое решение
+ G — лучшее сохранённое решение
+ M — в меню
@@ -1722,9 +1726,9 @@ function autoPlayStep() {
tryMove(dx, dy);
}
-function playBestSolution() {
+async function playBestSolution() {
if (autoSolveActive || levelComplete || solveState || playerMoving || boxes.some(b => b.moving)) return;
- const best = bestSolution(LEVELS[currentLevel].name);
+ const best = await bestSolution(LEVELS[currentLevel].name);
if (!best) { alert('Нет сохранённых решений для этого уровня — сначала пройди его (F или руками)'); return; }
startFlatPlayback(best.moves);
}
@@ -2080,6 +2084,7 @@ window.addEventListener('keydown', e => {
if (key === 'p') { currentLevel=(currentLevel-1+LEVELS.length)%LEVELS.length; loadLevel(currentLevel); e.preventDefault(); return; }
if (key === 'f') { startAutoSolve(); e.preventDefault(); return; }
if (key === 'g') { playBestSolution(); e.preventDefault(); return; }
+ if (key === 'm') { backToMenu(); e.preventDefault(); return; }
// Стрелки и WASD
if (['arrowup','arrowdown','arrowleft','arrowright','w','a','s','d'].includes(key)) {
@@ -2149,14 +2154,31 @@ document.getElementById('start-begin').addEventListener('click', () => {
});
document.getElementById('end-menu').addEventListener('click', () => showScreen('screen-menu'));
+// Выход в меню из игры — гасим поиск/автопроигрывание, если шли, иначе
+// они продолжат тикать в фоне за скрытым экраном.
+function backToMenu() {
+ if (solveState) cancelAutoSolve();
+ autoSolveActive = false;
+ autoPlayMoves = null;
+ showScreen('screen-menu');
+}
+document.getElementById('menu-btn').addEventListener('click', backToMenu);
+
document.getElementById('settings-save').addEventListener('click', async () => {
const name = document.getElementById('settings-name-input').value.trim();
if (!name) return;
+ const btn = document.getElementById('settings-save');
+ btn.disabled = true;
+ const originalText = btn.textContent;
+ btn.textContent = 'Сохраняю…';
try {
await apiPost('set_name', { name });
showScreen(settingsReturnTo === null ? 'screen-menu' : settingsReturnTo);
} catch {
alert('Не удалось сохранить имя — сервер недоступен');
+ } finally {
+ btn.disabled = false;
+ btn.textContent = originalText;
}
});
document.getElementById('settings-name-input').addEventListener('keydown', e => {