ChessNut/frontend/public/game.html
2025-10-18 23:21:30 +02:00

131 lines
7.3 KiB
HTML
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!doctype html>
<html lang="fr">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>ChessNut 1 Partie</title>
<link rel="stylesheet" href="src/styles.css">
<style>
/* Minimal board CSS: keep responsive wrapper but delegate main layout to linked stylesheet */
.game-page{max-width:1000px;margin:12px auto;padding:8px}
#board-wrapper{width:100%;max-width:900px;margin:0 auto}
/* keep a wrapper that forces a square area; the actual .board/.cell layout lives in src/styles.css */
#board-wrapper .board{width:100%;aspect-ratio:1/1;box-sizing:border-box}
.cell .piece{width:100%;height:100%;object-fit:contain;display:block}
.cell.selected{outline:3px solid rgba(0,128,255,0.6);}
/* grid cells will be created dynamically via JS using grid-template */
/* checkerboard colors handled by .cell.light/.cell.dark in src/styles.css */
#meta{margin-top:8px}
</style>
</head>
<body>
<div class="game-page">
<header><h1>Partie</h1></header>
<div id="meta">Chargement...</div>
<div id="player-color" style="margin-top:6px;font-weight:600">Couleur: —</div>
<div id="players-panel" style="margin-top:8px;font-size:14px">
<strong>Joueurs:</strong>
<ul id="players-list" style="list-style:none;padding-left:0;margin-top:6px"></ul>
</div>
<div id="server-load-indicator" style="margin-top:6px;color:#666">Chargement de l'état du serveur...</div>
<div id="board-wrapper"><div id="board-container"></div></div>
<div style="margin-top:8px">
</div>
</div>
<script src="https://cdn.socket.io/4.5.4/socket.io.min.js"></script>
<script src="src/game.js?v=4"></script>
<script>
// small bootstrap: fetch initial game state and wire socket updates
(function(){
const qs = new URLSearchParams(window.location.search);
const gid = qs.get('game');
const meta = document.getElementById('meta');
if(!gid){ meta.textContent = 'Game ID manquant'; return; }
meta.textContent = 'Affichage du plateau...';
// render an empty board immediately so user always sees a board even if backend is slow/unavailable
try { if(typeof renderBoardFromState === 'function') renderBoardFromState(null); } catch(e){ console.warn('initial empty board render failed', e); }
// fetch initial state: prefer explicit backend host then fallback to same-origin
(function(){
function handleGameObj(g){
// set globals expected by src/game.js so socket handlers attach correctly
try {
currentGameId = gid;
// prefer a session-scoped stored player id for this game (persisted at join/create)
try{
// support multiple possible sessionStorage key formats used across the app
const candidateKeys = [
'chessnut:game:' + gid + ':playerId', // older/other modules
'playerId:' + gid // newer lightweight key used elsewhere
];
let stored = null;
for (const k of candidateKeys) {
stored = sessionStorage.getItem(k);
if (stored) { myPlayerId = stored; break; }
}
// if still not found, fall back to first player from server and persist under both keys
if (!stored && g && g.players && g.players[0]) {
myPlayerId = g.players[0].id;
try{
sessionStorage.setItem('chessnut:game:' + gid + ':playerId', myPlayerId);
sessionStorage.setItem('playerId:' + gid, myPlayerId);
}catch(e){}
}
}catch(e){}
// remember the last received game object and compute this client's assigned color (if any)
window.lastGameObj = g;
if (g && g.players && myPlayerId) {
const me = g.players.find(p => p.id === myPlayerId);
window.myColor = me && me.colorAssigned ? me.colorAssigned : null;
const pc = document.getElementById('player-color'); if(pc) pc.textContent = 'Couleur: ' + (window.myColor || 'non assignée');
}
// render board from state or empty board (after computing myColor so render can honor orientation)
if(g && g.state && typeof renderBoardFromState === 'function') renderBoardFromState(g.state);
else if(typeof renderBoardFromState === 'function') renderBoardFromState(null);
const sli = document.getElementById('server-load-indicator'); if(sli) sli.style.display = 'none';
if(typeof socket === 'undefined' || !socket){
socket = io();
socket.on('connect', () => { socket.emit('join-game', gid); socket.emit('identify', { gameId: gid, playerId: myPlayerId }); });
socket.on('game-state', (s) => { if(typeof renderBoardFromState === 'function') renderBoardFromState(s); if(typeof setMeta === 'function') setMeta('game-state updated'); });
socket.on('move', (m) => { if(typeof setMeta === 'function') setMeta('remote move ' + JSON.stringify(m)); });
socket.on('player-update', (g) => {
// update local cached game object, render players list and recompute myColor when players list changes
try{
window.lastGameObj = g;
if (g) { try{ renderPlayersList(g); }catch(e){} }
if (g && g.players && myPlayerId) {
const me = g.players.find(p => p.id === myPlayerId);
window.myColor = me && me.colorAssigned ? me.colorAssigned : window.myColor;
const pc = document.getElementById('player-color'); if(pc) pc.textContent = 'Couleur: ' + (window.myColor || 'non assignée');
}
// re-render board to apply orientation change if colorAssigned arrived late
if (typeof renderBoardFromState === 'function' && g && g.state) renderBoardFromState(g.state);
}catch(e){}
if(typeof setMeta === 'function') setMeta('players updated');
});
}
// ensure players list is rendered on initial load
try{ if(window.lastGameObj) renderPlayersList(window.lastGameObj); }catch(e){}
} catch(e){ console.warn('socket init failed', e); }
}
fetch('http://localhost:4000/api/game/' + gid).then(r => r.ok ? r.json() : null).then(g => {
if(g) { handleGameObj(g); }
else {
// try same-origin
fetch('/api/game/' + gid).then(r => r.ok ? r.json() : null).then(handleGameObj).catch(()=>{ handleGameObj(null); const sli = document.getElementById('server-load-indicator'); if(sli) sli.textContent = 'Serveur injoignable'; });
}
}).catch(()=>{
fetch('/api/game/' + gid).then(r => r.ok ? r.json() : null).then(handleGameObj).catch(()=>{ handleGameObj(null); const sli = document.getElementById('server-load-indicator'); if(sli) sli.textContent = 'Serveur injoignable'; });
});
})();
const leaveBtn = document.getElementById('leave');
if (leaveBtn) {
leaveBtn.addEventListener('click', ()=>{ window.location.href = 'waiting.html?game=' + encodeURIComponent(gid); });
}
})();
</script>
</body>
</html>