affichage de la bonne couleur

This commit is contained in:
Didictateur 2025-11-08 21:14:47 +01:00
parent af6bcf60c5
commit bafd0fb153
4 changed files with 78 additions and 21 deletions

View file

@ -7,7 +7,7 @@
</head> </head>
<body> <body>
<h2>ChessNut — Partie</h2> <h2>ChessNut — Partie</h2>
<div>Room: <strong id="roomId">-</strong> <div>Room: <strong id="roomId">-</strong> &nbsp;&nbsp; Vous jouez: <strong id="myColor">-</strong>
<div class="layout-row"> <div class="layout-row">
<div> <div>
<div id="board"></div> <div id="board"></div>
@ -42,7 +42,9 @@
const fenEl = document.getElementById('fen'); const fenEl = document.getElementById('fen');
const playersEl = document.getElementById('players'); const playersEl = document.getElementById('players');
const boardEl = document.getElementById('board'); const boardEl = document.getElementById('board');
const myColorEl = document.getElementById('myColor');
let socket = null; let socket = null;
let myColor = null;
// safe logger: prefer on-page log if present, otherwise console // safe logger: prefer on-page log if present, otherwise console
function log(...args){ function log(...args){
@ -91,6 +93,19 @@
socket.emit('room:join', { roomId, playerId }, (resp)=>{ socket.emit('room:join', { roomId, playerId }, (resp)=>{
if(resp && resp.error){ log('join error', resp); alert(resp.error); return; } if(resp && resp.error){ log('join error', resp); alert(resp.error); return; }
log('Rejoint room', resp); log('Rejoint room', resp);
// remember assigned id/color from server
if(resp.playerId){
if(playerIdEl) playerIdEl.textContent = resp.playerId;
}
if(resp.color){
myColor = resp.color;
if(myColorEl) myColorEl.textContent = myColor;
// orient board for black
if(boardEl){
if(myColor === 'black') boardEl.classList.add('flipped');
else boardEl.classList.remove('flipped');
}
}
}); });
} }

View file

@ -52,6 +52,10 @@ a:hover{text-decoration:underline}
.square.dark{background: linear-gradient(180deg, rgba(0,0,0,0.18), rgba(0,0,0,0.12));} .square.dark{background: linear-gradient(180deg, rgba(0,0,0,0.18), rgba(0,0,0,0.12));}
.square{border:1px solid rgba(0,0,0,0.06)} .square{border:1px solid rgba(0,0,0,0.06)}
/* flipped board for black perspective */
#board.flipped{transform:rotate(180deg)}
#board.flipped .square img{transform:rotate(180deg)}
/* Lobby / hero styles - decorative and fun */ /* Lobby / hero styles - decorative and fun */
.hero{ .hero{
display:flex;align-items:center;justify-content:space-between;padding:28px;border-radius:12px;margin-bottom:18px;overflow:hidden;position:relative;border:1px solid rgba(255,255,255,0.04); display:flex;align-items:center;justify-content:space-between;padding:28px;border-radius:12px;margin-bottom:18px;overflow:hidden;position:relative;border:1px solid rgba(255,255,255,0.04);

View file

@ -64,6 +64,10 @@ a:hover{text-decoration:underline}
.square.dark{background: linear-gradient(180deg, rgba(0,0,0,0.18), rgba(0,0,0,0.12));} .square.dark{background: linear-gradient(180deg, rgba(0,0,0,0.18), rgba(0,0,0,0.12));}
.square{border:1px solid rgba(0,0,0,0.06)} .square{border:1px solid rgba(0,0,0,0.06)}
/* flipped board for black perspective */
#board.flipped{transform:rotate(180deg)}
#board.flipped .square img{transform:rotate(180deg)}
/* Lobby / hero styles - decorative and fun */ /* Lobby / hero styles - decorative and fun */
.hero{ .hero{
display:flex;align-items:center;justify-content:space-between;padding:28px;border-radius:12px;margin-bottom:18px;overflow:hidden;position:relative;border:1px solid rgba(255,255,255,0.04); display:flex;align-items:center;justify-content:space-between;padding:28px;border-radius:12px;margin-bottom:18px;overflow:hidden;position:relative;border:1px solid rgba(255,255,255,0.04);

View file

@ -25,7 +25,7 @@ app.post('/rooms', (req, res) => {
// For standard 8x8 chess we use chess.js. For other sizes we keep a placeholder state // For standard 8x8 chess we use chess.js. For other sizes we keep a placeholder state
const chess = size === 8 ? new Chess() : null; const chess = size === 8 ? new Chess() : null;
// hostId will be set when the first player joins // hostId will be set when the first player joins
rooms.set(id, { id, chess, players: [], status: 'waiting', hostId: null, size, cards: {}, playedCards: [] }); rooms.set(id, { id, chess, players: [], status: 'waiting', hostId: null, size, cards: {}, playedCards: [], removalTimers: new Map() });
res.json({ roomId: id, size }); res.json({ roomId: id, size });
}); });
@ -43,10 +43,24 @@ io.on('connection', (socket) => {
const room = rooms.get(roomId); const room = rooms.get(roomId);
if (!room) return cb && cb({ error: 'room not found' }); if (!room) return cb && cb({ error: 'room not found' });
if (room.players.length >= 2) return cb && cb({ error: 'room full' }); if (room.players.length >= 2) return cb && cb({ error: 'room full' });
const assignedId = playerId || uuidv4(); const assignedId = playerId || uuidv4();
const color = room.players.length === 0 ? 'white' : 'black';
// If this player was pending removal (disconnect during navigation), cancel removal
if(room.removalTimers && room.removalTimers.has(assignedId)){
clearTimeout(room.removalTimers.get(assignedId));
room.removalTimers.delete(assignedId);
}
// If playerId corresponds to an existing player, treat this as a reconnection
let existing = room.players.find(p => p.id === assignedId);
let color;
if(existing){
existing.socketId = socket.id;
color = existing.color;
} else {
color = room.players.length === 0 ? 'white' : 'black';
room.players.push({ id: assignedId, socketId: socket.id, color }); room.players.push({ id: assignedId, socketId: socket.id, color });
}
socket.join(roomId); socket.join(roomId);
socket.data.roomId = roomId; socket.data.roomId = roomId;
socket.data.playerId = assignedId; socket.data.playerId = assignedId;
@ -124,15 +138,16 @@ io.on('connection', (socket) => {
if (!roomId) return; if (!roomId) return;
const room = rooms.get(roomId); const room = rooms.get(roomId);
if (!room) return; if (!room) return;
// delay removal to allow fast reconnects (e.g. navigation between pages)
room.players = room.players.filter(p => p.socketId !== socket.id); const playerId = socket.data.playerId;
if (room.players.length < 2 && room.status === 'playing') room.status = 'waiting'; if(playerId && room.removalTimers){
const t = setTimeout(()=>{
room.players = room.players.filter(p => p.id !== playerId);
// if the host left, promote the next player to host (or null) // if the host left, promote the next player to host (or null)
if (room.hostId && !room.players.find(p => p.id === room.hostId)) { if (room.hostId && !room.players.find(p => p.id === room.hostId)) {
room.hostId = room.players[0] ? room.players[0].id : null; room.hostId = room.players[0] ? room.players[0].id : null;
} }
if (room.players.length < 2 && room.status === 'playing') room.status = 'waiting';
io.to(roomId).emit('room:update', { io.to(roomId).emit('room:update', {
fen: room.chess ? room.chess.fen() : null, fen: room.chess ? room.chess.fen() : null,
players: room.players.map(p => ({ id: p.id, color: p.color })), players: room.players.map(p => ({ id: p.id, color: p.color })),
@ -141,6 +156,25 @@ io.on('connection', (socket) => {
size: room.size, size: room.size,
cards: Object.keys(room.cards || {}) cards: Object.keys(room.cards || {})
}); });
room.removalTimers.delete(playerId);
}, 5000);
room.removalTimers.set(playerId, t);
} else {
// fallback: immediate removal
room.players = room.players.filter(p => p.socketId !== socket.id);
if (room.players.length < 2 && room.status === 'playing') room.status = 'waiting';
if (room.hostId && !room.players.find(p => p.id === room.hostId)) {
room.hostId = room.players[0] ? room.players[0].id : null;
}
io.to(roomId).emit('room:update', {
fen: room.chess ? room.chess.fen() : null,
players: room.players.map(p => ({ id: p.id, color: p.color })),
status: room.status,
hostId: room.hostId,
size: room.size,
cards: Object.keys(room.cards || {})
});
}
}); });
// Provide legal moves for a given square (for standard 8x8 via chess.js) // Provide legal moves for a given square (for standard 8x8 via chess.js)