Commit 95029f8f authored by Mahmoud Aglan's avatar Mahmoud Aglan

fix: place 2-player Ludo on diagonal corners (Red vs Yellow)

- Default seats for 2 players: [0, 2] (BL vs TR) instead of [0, 1] (adjacent)
- Panel layout: opponent at top-right for 2-player (diagonally opposite)
- Corner glow uses boardSlot instead of player index
- Dim inactive home zones, home columns, center triangles, start squares
- Matches the getSeatPositions() in room.js which already returned [0, 2]
Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
parent 92bb521f
......@@ -73,7 +73,9 @@ export function mountGame(el, params) {
livePlayerIds = params.players || [];
// Determine active seat indices (which of [0,1,2,3] are playing)
const activeSeats = seats || [0, 1, 2, 3].slice(0, numPlayers);
// 2 players: diagonal (Red BL vs Yellow TR), 3 players: skip Yellow
const defaultSeats = numPlayers === 2 ? [0, 2] : numPlayers === 3 ? [0, 1, 3] : [0, 1, 2, 3];
const activeSeats = seats || defaultSeats;
if (mode === 'live' && params.players) {
PLAYER_NAMES = params.players.map((p, i) => {
......@@ -118,8 +120,8 @@ export function mountGame(el, params) {
el.innerHTML = `
<div style="display:flex;flex-direction:column;height:100%;background:linear-gradient(180deg,#0d0d1a 0%,#1a1a2e 50%,#0d0d1a 100%);justify-content:flex-end;">
<div style="display:flex;justify-content:space-between;padding:8px 12px;background:rgba(15,15,30,0.9);border-bottom:1px solid rgba(255,255,255,0.04);direction:ltr;">
${panels.length > 1 ? renderPanel(panels[1]) : '<div></div>'}
${panels.length > 2 ? renderPanel(panels[2]) : '<div></div>'}
${numPlayers === 2 ? '<div></div>' : (panels.length > 1 ? renderPanel(panels[1]) : '<div></div>')}
${numPlayers === 2 ? renderPanel(panels[1]) : (panels.length > 2 ? renderPanel(panels[2]) : '<div></div>')}
</div>
<div id="ludo-wrap" style="flex:1;display:flex;align-items:center;justify-content:center;padding:6px;min-height:0;"></div>
<div style="display:flex;justify-content:space-between;padding:8px 12px;background:rgba(15,15,30,0.9);border-top:1px solid rgba(255,255,255,0.04);direction:ltr;">
......@@ -904,10 +906,11 @@ function renderFrame() {
// === Ambient corner glow (animated, lightweight) ===
if (game && !game.gameOver) {
const cp = game.currentPlayer;
const slot = game.players[cp]?.boardSlot ?? cp;
const corners = [[0,boardSize],[0,0],[boardSize,0],[boardSize,boardSize]];
const [gx, gy] = corners[cp];
const [gx, gy] = corners[slot];
const ambGrad = ctx.createRadialGradient(gx, gy, 0, gx, gy, cs*5);
ambGrad.addColorStop(0, COLORS[cp] + '20');
ambGrad.addColorStop(0, COLORS[slot] + '20');
ambGrad.addColorStop(1, 'transparent');
ctx.fillStyle = ambGrad;
ctx.fillRect(0, 0, boardSize, boardSize);
......@@ -956,8 +959,11 @@ function drawStaticBoard() {
sctx.fillStyle = '#FAFAFA';
sctx.fillRect(0, 0, boardSize, boardSize);
// Home zones
// Home zones (dim inactive seats in <4 player games)
const activeSlotsSet = new Set(game.activeSeats || [0,1,2,3]);
[[0,0,9],[1,0,0],[2,9,0],[3,9,9]].forEach(([p,c,r]) => {
const active = activeSlotsSet.has(p);
sctx.globalAlpha = active ? 1.0 : 0.2;
sctx.fillStyle = COLORS[p];
sctx.fillRect(c*cs, r*cs, 6*cs, 6*cs);
sctx.fillStyle = '#FAFAFA';
......@@ -966,6 +972,7 @@ function drawStaticBoard() {
sctx.strokeStyle = COLORS[p];
sctx.lineWidth = 2.5;
sctx.strokeRect(c*cs+ins+3, r*cs+ins+3, 6*cs-ins*2-6, 6*cs-ins*2-6);
sctx.globalAlpha = 1.0;
});
// Cross paths
......@@ -989,28 +996,37 @@ function drawStaticBoard() {
sctx.beginPath(); sctx.moveTo((i+9)*cs,6*cs); sctx.lineTo((i+9)*cs,9*cs); sctx.stroke();
}
// Home columns
for (let p = 0; p < 4; p++) HOME_COLUMNS[p].forEach(([col,row]) => { sctx.fillStyle = COLORS_LIGHT[p]; sctx.fillRect(col*cs+1, row*cs+1, cs-2, cs-2); });
// Home columns (dim inactive)
for (let p = 0; p < 4; p++) {
sctx.globalAlpha = activeSlotsSet.has(p) ? 1.0 : 0.2;
HOME_COLUMNS[p].forEach(([col,row]) => { sctx.fillStyle = COLORS_LIGHT[p]; sctx.fillRect(col*cs+1, row*cs+1, cs-2, cs-2); });
}
sctx.globalAlpha = 1.0;
// Safe squares
SAFE_SQUARES.forEach(idx => { const [col,row] = SHARED_PATH[idx]; sctx.fillStyle = '#FFF9C4'; sctx.fillRect(col*cs+1,row*cs+1,cs-2,cs-2); sctx.fillStyle = '#F9A825'; sctx.font = `${cs*0.45}px sans-serif`; sctx.textAlign = 'center'; sctx.textBaseline = 'middle'; sctx.fillText('★', col*cs+cs/2, row*cs+cs/2); });
// Center triangles
// Center triangles (dim inactive)
const cx = 7.5*cs, cy = 7.5*cs, hs = 1.5*cs;
sctx.fillStyle = COLORS[0]; sctx.beginPath();
sctx.moveTo(cx-hs, cy+hs); sctx.lineTo(cx+hs, cy+hs); sctx.lineTo(cx, cy); sctx.closePath(); sctx.fill();
sctx.fillStyle = COLORS[1]; sctx.beginPath();
sctx.moveTo(cx-hs, cy-hs); sctx.lineTo(cx-hs, cy+hs); sctx.lineTo(cx, cy); sctx.closePath(); sctx.fill();
sctx.fillStyle = COLORS[2]; sctx.beginPath();
sctx.moveTo(cx-hs, cy-hs); sctx.lineTo(cx+hs, cy-hs); sctx.lineTo(cx, cy); sctx.closePath(); sctx.fill();
sctx.fillStyle = COLORS[3]; sctx.beginPath();
sctx.moveTo(cx+hs, cy-hs); sctx.lineTo(cx+hs, cy+hs); sctx.lineTo(cx, cy); sctx.closePath(); sctx.fill();
const triPaths = [
[0, [cx-hs,cy+hs], [cx+hs,cy+hs], [cx,cy]], // Red bottom
[1, [cx-hs,cy-hs], [cx-hs,cy+hs], [cx,cy]], // Green left
[2, [cx-hs,cy-hs], [cx+hs,cy-hs], [cx,cy]], // Yellow top
[3, [cx+hs,cy-hs], [cx+hs,cy+hs], [cx,cy]], // Blue right
];
triPaths.forEach(([p, a, b, c2]) => {
sctx.globalAlpha = activeSlotsSet.has(p) ? 1.0 : 0.15;
sctx.fillStyle = COLORS[p]; sctx.beginPath();
sctx.moveTo(a[0],a[1]); sctx.lineTo(b[0],b[1]); sctx.lineTo(c2[0],c2[1]); sctx.closePath(); sctx.fill();
});
sctx.globalAlpha = 1.0;
sctx.strokeStyle = '#fff'; sctx.lineWidth = 1.5;
sctx.strokeRect(cx-hs, cy-hs, hs*2, hs*2);
// Start position squares
const startColors = [[6,13,'#FFCDD2'],[1,6,'#C8E6C9'],[8,1,'#FFF9C4'],[13,8,'#BBDEFB']];
startColors.forEach(([col,row,color]) => { sctx.fillStyle = color; sctx.fillRect(col*cs+1, row*cs+1, cs-2, cs-2); });
// Start position squares (dim inactive)
const startColors = [[0,6,13,'#FFCDD2'],[1,1,6,'#C8E6C9'],[2,8,1,'#FFF9C4'],[3,13,8,'#BBDEFB']];
startColors.forEach(([p,col,row,color]) => { sctx.globalAlpha = activeSlotsSet.has(p) ? 1.0 : 0.2; sctx.fillStyle = color; sctx.fillRect(col*cs+1, row*cs+1, cs-2, cs-2); });
sctx.globalAlpha = 1.0;
}
function drawPieces(cs) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment