add game record display overflow canvas for moves made at previously played points
This commit is contained in:
parent
9ed4fc0a39
commit
a290ec532d
2 changed files with 122 additions and 20 deletions
|
@ -8,8 +8,14 @@ const Menu = ({ showMenu, clickClose, ...props }) => {
|
||||||
if (e.target.className === "Game__Menu-container") clickClose();
|
if (e.target.className === "Game__Menu-container") clickClose();
|
||||||
};
|
};
|
||||||
const canvasRef = useRef();
|
const canvasRef = useRef();
|
||||||
|
const overflowRef = useRef();
|
||||||
const drawGameRecord = () => {
|
const drawGameRecord = () => {
|
||||||
return <canvas ref={canvasRef} />;
|
return (
|
||||||
|
<>
|
||||||
|
<canvas ref={canvasRef} />
|
||||||
|
<canvas ref={overflowRef} />
|
||||||
|
</>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -35,7 +41,49 @@ const Menu = ({ showMenu, clickClose, ...props }) => {
|
||||||
ctx.stroke();
|
ctx.stroke();
|
||||||
}
|
}
|
||||||
if (!meta?.gameRecord) return;
|
if (!meta?.gameRecord) return;
|
||||||
meta.gameRecord.forEach(({ player, pos }, index) => {
|
ctx.textAlign = "center";
|
||||||
|
ctx.textBaseline = "middle";
|
||||||
|
const { overflow } = meta.gameRecord.reduce(
|
||||||
|
(dict, { player, pos }, index) => {
|
||||||
|
const past = dict[`${pos.x}-${pos.y}`];
|
||||||
|
if (past) {
|
||||||
|
// overflow: [ { move:#, player:'color', subsequentMoves: [ { move: #, player: 'color' } ] } ]
|
||||||
|
if (dict.overflow) {
|
||||||
|
const indexOfPrior = dict.overflow.findIndex(
|
||||||
|
({ move }) => move === past
|
||||||
|
);
|
||||||
|
if (indexOfPrior !== -1) {
|
||||||
|
// if multiple past moves at this point exist
|
||||||
|
dict.overflow[indexOfPrior].subsequentMoves.push({
|
||||||
|
move: index + 1,
|
||||||
|
player,
|
||||||
|
});
|
||||||
|
return dict;
|
||||||
|
}
|
||||||
|
// if a second move at this point has not yet been encountered
|
||||||
|
// prior move will be black if no active handicap and move is odd or if active handicap and move is even
|
||||||
|
const playerPrior =
|
||||||
|
(active.handicap && !(past % 2)) || past % 2 ? "black" : "white";
|
||||||
|
return {
|
||||||
|
...dict,
|
||||||
|
overflow: [
|
||||||
|
...dict.overflow,
|
||||||
|
{
|
||||||
|
move: past,
|
||||||
|
player: playerPrior,
|
||||||
|
subsequentMoves: [{ move: index + 1, player }],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// if no move has yet been encountered at a previously made move
|
||||||
|
return {
|
||||||
|
...dict,
|
||||||
|
overflow: [
|
||||||
|
{ move: past, subsequentMoves: [{ move: index + 1, player }] },
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
ctx.arc(
|
ctx.arc(
|
||||||
(pos.y - 1) * space + offset,
|
(pos.y - 1) * space + offset,
|
||||||
|
@ -49,15 +97,67 @@ const Menu = ({ showMenu, clickClose, ...props }) => {
|
||||||
ctx.fillStyle = player === "white" ? "#fff" : "#000";
|
ctx.fillStyle = player === "white" ? "#fff" : "#000";
|
||||||
ctx.fill();
|
ctx.fill();
|
||||||
ctx.fillStyle = player === "white" ? "#000" : "#fff";
|
ctx.fillStyle = player === "white" ? "#000" : "#fff";
|
||||||
ctx.textAlign = "center";
|
|
||||||
ctx.textBaseline = "middle";
|
|
||||||
ctx.fillText(
|
ctx.fillText(
|
||||||
index + 1,
|
index + 1,
|
||||||
(pos.y - 1) * space + offset,
|
(pos.y - 1) * space + offset,
|
||||||
(pos.x - 1) * space + offset
|
(pos.x - 1) * space + offset
|
||||||
);
|
);
|
||||||
|
return { ...dict, [`${pos.x}-${pos.y}`]: index + 1 };
|
||||||
|
},
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
if (!overflow?.length) return;
|
||||||
|
// Draw Overflow Moves (moves made at prior points)
|
||||||
|
const canvas2 = overflowRef.current;
|
||||||
|
const ctx2 = canvas2.getContext("2d");
|
||||||
|
canvas2.width = scale;
|
||||||
|
canvas2.height = space * overflow.length;
|
||||||
|
ctx2.textAlign = "center";
|
||||||
|
ctx2.textBaseline = "middle";
|
||||||
|
overflow.forEach(({ move, subsequentMoves, player }, index) => {
|
||||||
|
subsequentMoves.forEach(({ player, move }, subIndex) => {
|
||||||
|
ctx2.beginPath();
|
||||||
|
ctx2.arc(
|
||||||
|
subIndex * space + offset,
|
||||||
|
index * space + offset,
|
||||||
|
offset * 0.95,
|
||||||
|
0,
|
||||||
|
Math.PI * 2,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
ctx2.stroke();
|
||||||
|
ctx2.fillStyle = player === "white" ? "#fff" : "#000";
|
||||||
|
ctx2.fill();
|
||||||
|
ctx2.fillStyle = player === "white" ? "#000" : "#fff";
|
||||||
|
ctx2.fillText(move, subIndex * space + offset, index * space + offset);
|
||||||
});
|
});
|
||||||
}, [showMenu, meta]);
|
ctx2.fillStyle = "#000";
|
||||||
|
ctx2.fillText(
|
||||||
|
"at",
|
||||||
|
subsequentMoves.length * space + offset,
|
||||||
|
index * space + offset
|
||||||
|
);
|
||||||
|
ctx2.fillStyle = player === "white" ? "#fff" : "#000";
|
||||||
|
ctx2.beginPath();
|
||||||
|
ctx2.arc(
|
||||||
|
(subsequentMoves.length + 1) * space + offset,
|
||||||
|
index * space + offset,
|
||||||
|
offset * 0.95,
|
||||||
|
0,
|
||||||
|
Math.PI * 2,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
ctx2.fill();
|
||||||
|
ctx2.stroke();
|
||||||
|
ctx2.fillStyle = player === "white" ? "#000" : "#fff";
|
||||||
|
ctx2.fillText(
|
||||||
|
move,
|
||||||
|
(subsequentMoves.length + 1) * space + offset,
|
||||||
|
index * space + offset
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}, [showMenu, meta, active.handicap, boardSize]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
@ -68,7 +168,6 @@ const Menu = ({ showMenu, clickClose, ...props }) => {
|
||||||
<button onClick={clickClose}>X</button>
|
<button onClick={clickClose}>X</button>
|
||||||
<div className="Game__Menu__game-record-container">
|
<div className="Game__Menu__game-record-container">
|
||||||
{drawGameRecord()}
|
{drawGameRecord()}
|
||||||
<div className="Game__Menu__game-record-overflow"></div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -5,6 +5,7 @@ div.Game__Menu-container {
|
||||||
|
|
||||||
background: rgba(0,0,0,0.5);
|
background: rgba(0,0,0,0.5);
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex-flow: column nowrap;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
|
@ -14,8 +15,10 @@ div.Game__Menu-container {
|
||||||
|
|
||||||
.Game__Menu-container__Menu {
|
.Game__Menu-container__Menu {
|
||||||
background: #eef;
|
background: #eef;
|
||||||
width: 80vw;
|
max-height: 90vh;
|
||||||
min-height: 20vh;
|
max-width: 80vw;
|
||||||
|
padding: 2vh;
|
||||||
|
overflow: scroll;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.Game__Menu__game-record-container {
|
div.Game__Menu__game-record-container {
|
||||||
|
|
Loading…
Reference in a new issue