feat: add player Names Throughout the Game UI

This commit is contained in:
2026-08-30 01:02:34 +03:00
parent 4d9d0db02d
commit dfc6b023f7
12 changed files with 307 additions and 34 deletions
+22 -12
View File
@@ -67,8 +67,8 @@
return item;
};
ui.availability.replaceChildren(
availabilityItem(`Игрок 1: ${info.player1Available ? 'свободен' : 'занят'}`),
availabilityItem(`Игрок 2: ${info.player2Available ? 'свободен' : 'занят'}`),
availabilityItem(`Игрок 1: ${info.player1Available ? 'свободен' : role === 'player1' ? 'Вы' : info.player1Name || 'занят'}`),
availabilityItem(`Игрок 2: ${info.player2Available ? 'свободен' : role === 'player2' ? 'Вы' : info.player2Name || 'занят'}`),
availabilityItem(`зрительских мест: ${info.spectatorsAvailable}`),
);
if (state?.phase === 'lobby') renderLobby();
@@ -110,6 +110,7 @@
payload.boards.every(board => typeof board === 'string' && /^[01234]{100}$/.test(board)) &&
typeof payload.version === 'number' && typeof payload.gameId === 'number' &&
(payload.winner === null || payload.winner === 0 || payload.winner === 1) && Array.isArray(payload.statistics) &&
Array.isArray(payload.players) && payload.players.length === 2 && payload.players.every(name => typeof name === 'string' && name.length <= 80) &&
payload.statistics.length === 2 && payload.statistics.every(entry => Array.isArray(entry) && entry.length === 4 &&
entry.every(value => Number.isInteger(value) && value >= 0));
}
@@ -134,7 +135,14 @@
target.x >= 0 && target.x < 10 && target.y >= 0 && target.y < 10 &&
state.boards[opponentIndex()][target.y * 10 + target.x] === '0';
}
function playerLabel(index) { return index === 1 && state?.mode === 'bot' ? 'ESP32' : `Игрок ${index + 1}`; }
function playerName(index) {
const name = state?.players?.[index];
return typeof name === 'string' && name.trim() ? name : `Игрок ${index + 1}`;
}
function playerLabel(index) {
if (index === 1 && state?.mode === 'bot') return 'ESP32';
return isPlayer() && index === ownIndex() ? 'Вы' : playerName(index);
}
async function fireTarget(target) {
if (!canFireTarget(target)) return false;
@@ -221,12 +229,12 @@
function boardDefinitions(result = false) {
if (role === 'spectator' || result) return [
{ index: 0, title: 'Поле игрока 1', key: 'player1', targetable: false },
{ index: 1, title: 'Поле игрока 2', key: 'player2', targetable: false }
{ index: 0, title: `Поле: ${playerLabel(0)}`, key: 'player1', targetable: false },
{ index: 1, title: `Поле: ${playerLabel(1)}`, key: 'player2', targetable: false }
];
return [
{ index: ownIndex(), title: 'Моё поле', key: 'own', targetable: false },
{ index: opponentIndex(), title: state.mode === 'bot' ? 'Поле ESP32' : 'Поле соперника', key: 'opponent', targetable: canShoot() }
{ index: opponentIndex(), title: state.mode === 'bot' ? 'Поле ESP32' : `Поле: ${playerName(opponentIndex())}`, key: 'opponent', targetable: canShoot() }
];
}
@@ -242,7 +250,8 @@
ui.tabs.replaceChildren();
definitions.forEach(definition => {
const tab = document.createElement('button');
tab.type = 'button'; tab.role = 'tab'; tab.textContent = definition.title;
tab.type = 'button'; tab.role = 'tab'; tab.textContent = definition.key === 'opponent' ? playerLabel(definition.index) : definition.title;
tab.title = definition.title; tab.setAttribute('aria-label', definition.title);
tab.setAttribute('aria-selected', String(definition.key === activeBoard));
tab.addEventListener('click', () => { activeBoard = definition.key; renderGame(); });
ui.tabs.append(tab);
@@ -253,7 +262,8 @@
function renderLobby() {
showScreen('lobby');
const playerOne = role === 'player1';
ui.lobbyDescription.textContent = role === 'spectator' ? 'Вы наблюдаете за подготовкой партии.' : 'Ожидайте готовности партии или настройте режим.';
const opponent = state.mode === 'bot' ? 'ESP32' : playerName(opponentIndex());
ui.lobbyDescription.textContent = role === 'spectator' ? 'Вы наблюдаете за подготовкой партии.' : state.mode === 'human' && info?.player2Available ? 'Ожидаем соперника.' : `Ожидаем готовности ${opponent}.`;
ui.modeControls.hidden = !playerOne;
if (playerOne) startLobbyInfoPolling();
else stopLobbyInfoPolling();
@@ -265,8 +275,8 @@
button.disabled = !playerOne;
});
ui.start.disabled = !canStart;
ui.modeDescription.textContent = state.mode === 'human' ? (playerTwoReady ? 'Второй игрок готов. Можно начать партию.' : 'Ожидаем подключения второго игрока.') : 'Игра против ESP32. Можно начать сразу.';
ui.lobbyHelp.textContent = playerOne ? '' : 'Игрок 1 выбирает режим и запускает партию.';
ui.modeDescription.textContent = state.mode === 'human' ? (playerTwoReady ? `${playerName(1)} готов. Можно начать партию.` : 'Ожидаем соперника.') : 'Игра против ESP32. Можно начать сразу.';
ui.lobbyHelp.textContent = playerOne ? '' : `${playerName(0)} выбирает режим и запускает партию.`;
}
function renderGame() {
@@ -275,7 +285,7 @@
showScreen('game');
if (canShoot() && !selectedTarget) activeBoard = 'opponent';
ui.turn.textContent = canShoot() ? 'Ваш ход' : `Ходит ${playerLabel(state.turn === 'player2' ? 1 : 0)}`;
ui.wins.textContent = `Победы: ${state.wins[0]} : ${state.wins[1]}`;
ui.wins.textContent = `${playerLabel(0)} ${state.wins[0]} : ${state.wins[1]} ${playerLabel(1)}`;
renderBoards(ui.boards);
const available = canShoot();
ui.shotControls.hidden = !isPlayer();
@@ -291,7 +301,7 @@
showScreen('result');
if (statisticsGameId !== state.gameId) refreshStatistics();
const waiting = state.phase === 'rematch_wait';
const winner = state.winner === 0 || state.winner === 1 ? `Победил ${playerLabel(state.winner)}. ` : '';
const winner = state.winner === ownIndex() && isPlayer() ? 'Вы победили. ' : state.winner === 0 || state.winner === 1 ? `Победил ${playerLabel(state.winner)}. ` : '';
const matchSummary = state.statistics.map((entry, index) => `${playerLabel(index)}: выстрелы ${entry[0]}, попадания ${entry[1]}, промахи ${entry[2]}, потоплено ${entry[3]}.`).join(' ');
const cumulative = cumulativeStatistics?.cumulative?.map((entry, index) => `${playerLabel(index)} всего: игр ${entry[0]}, побед ${entry[1]}, поражений ${entry[2]}, выстрелов ${entry[4]}, попаданий ${entry[5]}, промахов ${entry[6]}, потоплено ${entry[3]}.`).join(' ') || '';
ui.result.textContent = `${winner}${matchSummary} ${cumulative} ${waiting ? 'Ожидается подтверждение повторной игры.' : 'Поля раскрыты. Можно подтвердить повторную игру.'}`;