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();
|
||||
};
|
||||
const canvasRef = useRef();
|
||||
const overflowRef = useRef();
|
||||
const drawGameRecord = () => {
|
||||
return <canvas ref={canvasRef} />;
|
||||
return (
|
||||
<>
|
||||
<canvas ref={canvasRef} />
|
||||
<canvas ref={overflowRef} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -35,7 +41,49 @@ const Menu = ({ showMenu, clickClose, ...props }) => {
|
|||
ctx.stroke();
|
||||
}
|
||||
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.arc(
|
||||
(pos.y - 1) * space + offset,
|
||||
|
@ -49,15 +97,67 @@ const Menu = ({ showMenu, clickClose, ...props }) => {
|
|||
ctx.fillStyle = player === "white" ? "#fff" : "#000";
|
||||
ctx.fill();
|
||||
ctx.fillStyle = player === "white" ? "#000" : "#fff";
|
||||
ctx.textAlign = "center";
|
||||
ctx.textBaseline = "middle";
|
||||
|
||||
ctx.fillText(
|
||||
index + 1,
|
||||
(pos.y - 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 (
|
||||
<div
|
||||
|
@ -68,7 +168,6 @@ const Menu = ({ showMenu, clickClose, ...props }) => {
|
|||
<button onClick={clickClose}>X</button>
|
||||
<div className="Game__Menu__game-record-container">
|
||||
{drawGameRecord()}
|
||||
<div className="Game__Menu__game-record-overflow"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -5,6 +5,7 @@ div.Game__Menu-container {
|
|||
|
||||
background: rgba(0,0,0,0.5);
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100vh;
|
||||
|
@ -14,8 +15,10 @@ div.Game__Menu-container {
|
|||
|
||||
.Game__Menu-container__Menu {
|
||||
background: #eef;
|
||||
width: 80vw;
|
||||
min-height: 20vh;
|
||||
max-height: 90vh;
|
||||
max-width: 80vw;
|
||||
padding: 2vh;
|
||||
overflow: scroll;
|
||||
}
|
||||
|
||||
div.Game__Menu__game-record-container {
|
||||
|
|
Loading…
Reference in a new issue