affichage de la bonne couleur
This commit is contained in:
parent
af6bcf60c5
commit
bafd0fb153
4 changed files with 78 additions and 21 deletions
|
|
@ -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> • 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');
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
50
server.js
50
server.js
|
|
@ -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)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue