possibilité de jouer une partie
This commit is contained in:
parent
619c584572
commit
e64e96e61c
3 changed files with 95 additions and 6 deletions
|
|
@ -50,6 +50,8 @@
|
|||
const remoteSelections = {};
|
||||
// track remote moves: { playerId: [moves] }
|
||||
const remoteMoves = {};
|
||||
// current boardState cached locally
|
||||
let currentBoardState = null;
|
||||
|
||||
// safe logger: prefer on-page log if present, otherwise console
|
||||
function log(...args){
|
||||
|
|
@ -134,6 +136,16 @@
|
|||
}catch(e){ console.warn('game:select handler error', e); }
|
||||
});
|
||||
|
||||
socket.on('move:moved', (data) => {
|
||||
try{
|
||||
log('recv move:moved', data && { from: data.from, to: data.to });
|
||||
// clear any local selection (move completed) before re-render
|
||||
clearSelection(false);
|
||||
if(data && data.boardState) renderBoardFromState(data.boardState);
|
||||
if(data && data.boardState) updateTurnBanner(data.boardState);
|
||||
}catch(e){ console.warn('move:moved handler error', e); }
|
||||
});
|
||||
|
||||
socket.emit('room:join', { roomId, playerId }, (resp)=>{
|
||||
if(resp && resp.error){ log('join error', resp); alert(resp.error); return; }
|
||||
log('Rejoint room', resp);
|
||||
|
|
@ -296,6 +308,27 @@
|
|||
const square = sqEl.getAttribute('data-square');
|
||||
if(!square) return;
|
||||
|
||||
// If this square contains a move-marker (either clicked marker or square area), attempt the move.
|
||||
// Prefer the actual clicked marker if present, otherwise look for a marker element inside the square.
|
||||
const clickedMarker = ev.target.closest && ev.target.closest('.move-marker');
|
||||
const marker = clickedMarker || sqEl.querySelector('.move-marker');
|
||||
if(marker){
|
||||
// ignore remote player's markers
|
||||
const remoteBy = marker.dataset && marker.dataset.remoteBy;
|
||||
if(remoteBy && remoteBy !== myPlayerId){ log('marker belongs to remote player, ignoring'); return; }
|
||||
const to = marker.dataset && marker.dataset.to;
|
||||
const from = marker.dataset && marker.dataset.from ? marker.dataset.from : selectedSquare;
|
||||
if(!to || !from){ log('invalid marker metadata', { from, to }); return; }
|
||||
// only allow if it's our turn
|
||||
const myShort = (myColor && myColor[0]) || '';
|
||||
if(!currentBoardState || currentBoardState.turn !== myShort){ log('not your turn'); return; }
|
||||
socket.emit('game:move', { roomId, from, to }, (resp)=>{
|
||||
if(resp && resp.error){ log('move error', resp); alert(resp.error); }
|
||||
else { log('move sent', resp); }
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// clicked a piece -> select it (no legal moves requested)
|
||||
const pieceImg = ev.target.closest && ev.target.closest('img.piece');
|
||||
if(pieceImg){
|
||||
|
|
@ -316,6 +349,8 @@
|
|||
|
||||
function renderBoardFromState(boardState){
|
||||
if(!boardState) return;
|
||||
// cache boardState for client-side checks (turn etc.)
|
||||
currentBoardState = boardState;
|
||||
// clear existing pieces but keep squares if present
|
||||
const squares = boardEl.querySelectorAll('.square');
|
||||
squares.forEach(s=> s.innerHTML = '');
|
||||
|
|
|
|||
|
|
@ -56,9 +56,10 @@ a:hover{text-decoration:underline}
|
|||
.square .move-marker{
|
||||
position:absolute;
|
||||
left:50%;top:50%;transform:translate(-50%,-50%);
|
||||
width:18%;height:18%;border-radius:50%;pointer-events:none;background:rgba(96,165,250,0.95);
|
||||
box-shadow:0 2px 6px rgba(2,6,23,0.6);z-index:3;
|
||||
width:18%;height:18%;border-radius:50%;pointer-events:auto;cursor:pointer;background:rgba(96,165,250,0.95);
|
||||
box-shadow:0 2px 6px rgba(2,6,23,0.6);z-index:3;transition:transform 120ms ease, opacity 120ms ease;
|
||||
}
|
||||
.square .move-marker:hover{ transform:translate(-50%,-50%) scale(1.12); opacity:0.95 }
|
||||
|
||||
/* highlighted/selected square when a player selects a piece */
|
||||
.square.selected{
|
||||
|
|
|
|||
61
server.js
61
server.js
|
|
@ -237,11 +237,64 @@ io.on('connection', (socket) => {
|
|||
socket.on('game:move', ({ roomId, from, to, promotion }, cb) => {
|
||||
const room = rooms.get(roomId);
|
||||
if (!room) return cb && cb({ error: 'room not found' });
|
||||
// Basic move handling: validate turn, validate piece ownership, validate target is one of computeLegalMoves,
|
||||
// apply the move to room.boardState, handle captures, flip turn and broadcast the updated board.
|
||||
try{
|
||||
const senderId = socket.data.playerId;
|
||||
if(!senderId) return cb && cb({ error: 'not joined' });
|
||||
const roomPlayer = room.players.find(p => p.id === senderId);
|
||||
if(!roomPlayer) return cb && cb({ error: 'player not in room' });
|
||||
if(!room.boardState) return cb && cb({ error: 'no board state' });
|
||||
|
||||
// Move handling/validation is intentionally not implemented here.
|
||||
// Implement a function to validate & apply moves on the room.boardState and
|
||||
// then emit 'move:moved' with move details and updated room.boardState.
|
||||
return cb && cb({ error: 'move handling not implemented on server; implement custom engine' });
|
||||
const board = room.boardState;
|
||||
// determine player's color short form ('w'|'b')
|
||||
const playerColorShort = (roomPlayer.color && roomPlayer.color[0]) || null;
|
||||
if(!playerColorShort) return cb && cb({ error: 'invalid player color' });
|
||||
|
||||
// must be player's turn
|
||||
if(board.turn !== playerColorShort) return cb && cb({ error: 'not your turn' });
|
||||
|
||||
// find piece at 'from'
|
||||
const pieces = board.pieces || [];
|
||||
const moving = pieces.find(p => p.square === from);
|
||||
if(!moving) return cb && cb({ error: 'no piece at source' });
|
||||
if(moving.color !== playerColorShort) return cb && cb({ error: 'not your piece' });
|
||||
|
||||
// validate that 'to' is among legal moves
|
||||
const legal = computeLegalMoves(room, from) || [];
|
||||
const ok = legal.some(m => m.to === to);
|
||||
if(!ok) return cb && cb({ error: 'illegal move' });
|
||||
|
||||
// apply move: remove any piece on target (capture)
|
||||
const targetIndex = pieces.findIndex(p => p.square === to);
|
||||
if(targetIndex >= 0){
|
||||
// remove captured piece
|
||||
pieces.splice(targetIndex, 1);
|
||||
}
|
||||
// move the piece
|
||||
moving.square = to;
|
||||
|
||||
// advance version and flip turn
|
||||
board.version = (board.version || 0) + 1;
|
||||
board.turn = (board.turn === 'w') ? 'b' : 'w';
|
||||
|
||||
// broadcast move and new board state
|
||||
const moved = { playerId: senderId, from, to, boardState: board };
|
||||
io.to(roomId).emit('move:moved', moved);
|
||||
io.to(roomId).emit('room:update', {
|
||||
boardState: board,
|
||||
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 || {})
|
||||
});
|
||||
|
||||
return cb && cb({ ok: true, moved });
|
||||
}catch(err){
|
||||
console.error('game:move error', err);
|
||||
return cb && cb({ error: 'server error' });
|
||||
}
|
||||
});
|
||||
|
||||
// Host can start the game explicitly
|
||||
|
|
|
|||
Loading…
Reference in a new issue