WIP
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
import { BoardConfig, PiecesStyle } from "./../types";
|
||||
import { Material, MoveWithDetails } from "../game/Game_x";
|
||||
import { Style, BoardData } from "../types";
|
||||
import { BoardConfig, PiecesStyle, Position } from "./../types";
|
||||
import { Style } from "../types";
|
||||
import drawRectangle from "./layers/drawRectangle";
|
||||
import drawCoords from "./layers/drawCoords";
|
||||
import drawMoveIndicators from "./layers/drawMoveIndicators";
|
||||
@@ -37,14 +36,10 @@ class Board {
|
||||
private style: Style = boards.standard;
|
||||
private flipped: boolean = false;
|
||||
private header: { [key: string]: string | undefined } = {};
|
||||
private boardData: BoardData | null = null;
|
||||
private ctx: CanvasRenderingContext2D;
|
||||
private tempCtx: CanvasRenderingContext2D;
|
||||
// private boardData: BoardData | null = null;
|
||||
private borderVisible: boolean = true;
|
||||
private lastMove: MoveWithDetails | null = null;
|
||||
private lastMaterial: Material | undefined = undefined;
|
||||
public canvas: HTMLCanvasElement = document.createElement("canvas");
|
||||
private tempCanvas: HTMLCanvasElement = document.createElement("canvas");
|
||||
private lastPosition: Position | null = null;
|
||||
// private lastMaterial: Material | undefined = undefined;
|
||||
private background: HTMLCanvasElement | null = null;
|
||||
private extraInfo: boolean = true;
|
||||
private piecesStyle: PiecesStyle = "tatiana";
|
||||
@@ -54,6 +49,12 @@ class Board {
|
||||
private showChecks: boolean = true;
|
||||
private currentScreen: "title" | "move" = "move";
|
||||
|
||||
private ctx: CanvasRenderingContext2D;
|
||||
private tempCtx: CanvasRenderingContext2D;
|
||||
|
||||
private tempCanvas: HTMLCanvasElement = document.createElement("canvas");
|
||||
public canvas: HTMLCanvasElement = document.createElement("canvas");
|
||||
|
||||
constructor(config: Partial<BoardConfig> = {}) {
|
||||
const ctx = this.canvas.getContext("2d");
|
||||
const tempCtx = this.tempCanvas.getContext("2d");
|
||||
@@ -96,13 +97,8 @@ class Board {
|
||||
|
||||
if (this.currentScreen === "title") {
|
||||
await this.titleFrame(this.header);
|
||||
} else {
|
||||
await this.frame(
|
||||
this.boardData,
|
||||
this.header,
|
||||
this.lastMove,
|
||||
this.lastMaterial
|
||||
);
|
||||
} else if (this.lastPosition !== null) {
|
||||
await this.frame(this.lastPosition, this.header);
|
||||
}
|
||||
|
||||
this.render();
|
||||
@@ -174,30 +170,6 @@ class Board {
|
||||
return this;
|
||||
}
|
||||
|
||||
isCheck(move: MoveWithDetails | null) {
|
||||
if (!move) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return move.san.includes("+");
|
||||
}
|
||||
|
||||
isMate(move: MoveWithDetails | null) {
|
||||
if (!move) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return move.san.includes("#");
|
||||
}
|
||||
|
||||
getOppositeColor(color?: "w" | "b") {
|
||||
if (!color) {
|
||||
return;
|
||||
}
|
||||
|
||||
return color === "w" ? "b" : "w";
|
||||
}
|
||||
|
||||
async titleFrame(header: { [key: string]: string | undefined }) {
|
||||
this.currentScreen = "title";
|
||||
this.header = header;
|
||||
@@ -265,22 +237,12 @@ class Board {
|
||||
}
|
||||
|
||||
async frame(
|
||||
boardData: BoardData | null,
|
||||
header: { [key: string]: string | undefined },
|
||||
move: MoveWithDetails | null = null,
|
||||
material?: Material
|
||||
position: Position | null,
|
||||
header: { [key: string]: string | undefined }
|
||||
) {
|
||||
this.currentScreen = "move";
|
||||
this.lastMove = move;
|
||||
this.boardData = boardData;
|
||||
this.lastMaterial = material;
|
||||
|
||||
const check = this.isCheck(move)
|
||||
? this.getOppositeColor(move?.color)
|
||||
: undefined;
|
||||
const mate = this.isMate(move)
|
||||
? this.getOppositeColor(move?.color)
|
||||
: undefined;
|
||||
this.lastPosition = position;
|
||||
this.header = header;
|
||||
|
||||
this.tempCtx.clearRect(0, 0, this.size, this.size);
|
||||
|
||||
@@ -290,64 +252,59 @@ class Board {
|
||||
|
||||
this.tempCtx.drawImage((await this.background) as HTMLCanvasElement, 0, 0);
|
||||
|
||||
if (boardData !== null) {
|
||||
if (this.lastMove && this.showMoveIndicator) {
|
||||
await drawMoveIndicators(
|
||||
this.tempCtx,
|
||||
this.lastMove,
|
||||
this.squareSize,
|
||||
this.style,
|
||||
this.borderWidth,
|
||||
this.tiles,
|
||||
this.flipped,
|
||||
this.margin
|
||||
);
|
||||
}
|
||||
|
||||
if (!this.borderVisible && this.showCoords) {
|
||||
drawCoords(
|
||||
this.tempCtx,
|
||||
this.style.coords,
|
||||
this.squareSize,
|
||||
this.tiles,
|
||||
this.flipped,
|
||||
this.borderWidth,
|
||||
this.size,
|
||||
this.borderVisible,
|
||||
this.margin
|
||||
);
|
||||
}
|
||||
|
||||
const piecesShadow = false;
|
||||
|
||||
await drawPieces(
|
||||
if (this.lastPosition?.move && this.showMoveIndicator) {
|
||||
await drawMoveIndicators(
|
||||
this.tempCtx,
|
||||
boardData,
|
||||
this.lastPosition.move,
|
||||
this.squareSize,
|
||||
this.style,
|
||||
this.borderWidth,
|
||||
this.tiles,
|
||||
this.flipped,
|
||||
check && this.showChecks ? check : undefined,
|
||||
mate && this.showChecks ? mate : undefined,
|
||||
piecesShadow,
|
||||
this.margin,
|
||||
this.piecesStyle
|
||||
this.margin
|
||||
);
|
||||
}
|
||||
|
||||
if (this.extraInfo && header) {
|
||||
await drawExtraInfo(
|
||||
this.tempCtx,
|
||||
this.width,
|
||||
this.height,
|
||||
this.scale,
|
||||
this.margin,
|
||||
this.style,
|
||||
header,
|
||||
this.flipped,
|
||||
move?.end === 0,
|
||||
material && this.showMaterial ? material : undefined
|
||||
);
|
||||
}
|
||||
if (!this.borderVisible && this.showCoords) {
|
||||
drawCoords(
|
||||
this.tempCtx,
|
||||
this.style.coords,
|
||||
this.squareSize,
|
||||
this.tiles,
|
||||
this.flipped,
|
||||
this.borderWidth,
|
||||
this.size,
|
||||
this.borderVisible,
|
||||
this.margin
|
||||
);
|
||||
}
|
||||
|
||||
if (!this.lastPosition) {
|
||||
return;
|
||||
}
|
||||
|
||||
await drawPieces(
|
||||
this.tempCtx,
|
||||
this.lastPosition,
|
||||
this.squareSize,
|
||||
this.borderWidth,
|
||||
this.flipped,
|
||||
this.margin,
|
||||
this.piecesStyle
|
||||
);
|
||||
|
||||
if (this.extraInfo && header) {
|
||||
await drawExtraInfo(
|
||||
this.tempCtx,
|
||||
this.width,
|
||||
this.height,
|
||||
this.scale,
|
||||
this.margin,
|
||||
this.style,
|
||||
this.header,
|
||||
this.flipped,
|
||||
this.lastPosition
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { Material } from "../../game/Game_x";
|
||||
import { Style } from "./../../types";
|
||||
import { Style, Position } from "./../../types";
|
||||
import drawText from "./drawText";
|
||||
|
||||
const chessFontMapping: { [key: string]: string } = {
|
||||
@@ -20,8 +19,7 @@ const drawExtraInfo = async (
|
||||
style: Style,
|
||||
data: { [key: string]: string | undefined },
|
||||
flipped: boolean,
|
||||
lastMove: boolean,
|
||||
material?: Material
|
||||
position: Position
|
||||
) => {
|
||||
const fontSize = Math.round(20 * scale);
|
||||
let offsetX = (margin - fontSize) / 2;
|
||||
@@ -88,7 +86,7 @@ const drawExtraInfo = async (
|
||||
let rightMarginWhite = 0;
|
||||
let rightMarginBlack = 0;
|
||||
|
||||
if (lastMove && data.Result) {
|
||||
if (position.last && data.Result) {
|
||||
const [resultWhite, resultBlack] = data.Result.split("-");
|
||||
|
||||
const textWhite =
|
||||
@@ -125,76 +123,75 @@ const drawExtraInfo = async (
|
||||
rightMarginBlack = w + 20 * scale;
|
||||
}
|
||||
|
||||
if (material) {
|
||||
const textWhite = material.diff > 0 ? `+${Math.abs(material.diff)}` : "";
|
||||
const { diff, imbalance } = position.material;
|
||||
|
||||
rightMarginWhite += drawText(
|
||||
ctx,
|
||||
textWhite,
|
||||
"Fira Mono",
|
||||
fontSize,
|
||||
500,
|
||||
width - offsetX - rightMarginWhite,
|
||||
flipped ? offsetY : height - offsetY,
|
||||
"right"
|
||||
);
|
||||
const textWhite = diff > 0 ? `+${Math.abs(diff)}` : "";
|
||||
|
||||
const textBlack = material.diff < 0 ? `+${Math.abs(material.diff)}` : "";
|
||||
rightMarginWhite += drawText(
|
||||
ctx,
|
||||
textWhite,
|
||||
"Fira Mono",
|
||||
fontSize,
|
||||
500,
|
||||
width - offsetX - rightMarginWhite,
|
||||
flipped ? offsetY : height - offsetY,
|
||||
"right"
|
||||
);
|
||||
|
||||
rightMarginBlack += drawText(
|
||||
ctx,
|
||||
textBlack,
|
||||
"Fira Mono",
|
||||
fontSize,
|
||||
500,
|
||||
width - offsetX - rightMarginBlack,
|
||||
flipped ? height - offsetY : offsetY,
|
||||
"right"
|
||||
);
|
||||
const textBlack = diff < 0 ? `+${Math.abs(diff)}` : "";
|
||||
|
||||
for (const [piece, count] of Object.entries(material.imbalance.w)) {
|
||||
for (let i = 0; i < count; i++) {
|
||||
const textWidth = drawText(
|
||||
ctx,
|
||||
chessFontMapping[piece],
|
||||
"Chess",
|
||||
fontSize,
|
||||
500,
|
||||
width - offsetX - rightMarginWhite,
|
||||
(flipped ? offsetY : height - offsetY) - 2 * scale,
|
||||
"right"
|
||||
);
|
||||
rightMarginBlack += drawText(
|
||||
ctx,
|
||||
textBlack,
|
||||
"Fira Mono",
|
||||
fontSize,
|
||||
500,
|
||||
width - offsetX - rightMarginBlack,
|
||||
flipped ? height - offsetY : offsetY,
|
||||
"right"
|
||||
);
|
||||
|
||||
rightMarginWhite +=
|
||||
i === count - 1
|
||||
? textWidth * 0.85
|
||||
: piece === "p"
|
||||
? textWidth * 0.4
|
||||
: textWidth * 0.6;
|
||||
}
|
||||
for (const [piece, count] of Object.entries(imbalance.w)) {
|
||||
for (let i = 0; i < count; i++) {
|
||||
const textWidth = drawText(
|
||||
ctx,
|
||||
chessFontMapping[piece],
|
||||
"Chess",
|
||||
fontSize,
|
||||
500,
|
||||
width - offsetX - rightMarginWhite,
|
||||
(flipped ? offsetY : height - offsetY) - 2 * scale,
|
||||
"right"
|
||||
);
|
||||
|
||||
rightMarginWhite +=
|
||||
i === count - 1
|
||||
? textWidth * 0.85
|
||||
: piece === "p"
|
||||
? textWidth * 0.4
|
||||
: textWidth * 0.6;
|
||||
}
|
||||
}
|
||||
|
||||
for (const [piece, count] of Object.entries(material.imbalance.b)) {
|
||||
for (let i = 0; i < count; i++) {
|
||||
const textWidth = drawText(
|
||||
ctx,
|
||||
chessFontMapping[piece],
|
||||
"Chess",
|
||||
fontSize,
|
||||
500,
|
||||
width - offsetX - rightMarginBlack,
|
||||
(flipped ? height - offsetY : offsetY) - 2 * scale,
|
||||
"right"
|
||||
);
|
||||
for (const [piece, count] of Object.entries(imbalance.b)) {
|
||||
for (let i = 0; i < count; i++) {
|
||||
const textWidth = drawText(
|
||||
ctx,
|
||||
chessFontMapping[piece],
|
||||
"Chess",
|
||||
fontSize,
|
||||
500,
|
||||
width - offsetX - rightMarginBlack,
|
||||
(flipped ? height - offsetY : offsetY) - 2 * scale,
|
||||
"right"
|
||||
);
|
||||
|
||||
rightMarginBlack +=
|
||||
i === count - 1
|
||||
? textWidth * 0.85
|
||||
: piece === "p"
|
||||
? textWidth * 0.4
|
||||
: textWidth * 0.6;
|
||||
// i === count - 1 || piece !== "p" ? textWidth * 0.8 : textWidth * 0.4;
|
||||
}
|
||||
rightMarginBlack +=
|
||||
i === count - 1
|
||||
? textWidth * 0.85
|
||||
: piece === "p"
|
||||
? textWidth * 0.4
|
||||
: textWidth * 0.6;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,74 +1,56 @@
|
||||
import { BoardData, PieceType, PieceColor, PiecesStyle } from "../../types";
|
||||
import { Position, PieceType, PieceColor, PiecesStyle } from "../../types";
|
||||
import ImagesCache from "../loaders/PiecesCache";
|
||||
// import drawCircle from "./drawCircle";
|
||||
|
||||
const drawPieces = async (
|
||||
ctx: CanvasRenderingContext2D,
|
||||
board: BoardData,
|
||||
position: Position,
|
||||
squareSize: number,
|
||||
borderWidth: number,
|
||||
tiles: number,
|
||||
flipped: boolean,
|
||||
check: "b" | "w" | undefined,
|
||||
mate: "b" | "w" | undefined,
|
||||
shadow: boolean,
|
||||
margin: number,
|
||||
piecesStyle: PiecesStyle
|
||||
) => {
|
||||
for (let y = 0; y < 8; y++) {
|
||||
for (let x = 0; x < 8; x++) {
|
||||
if (board[y][x] !== null) {
|
||||
const { type, color } = board[y][x] as {
|
||||
type: PieceType;
|
||||
color: PieceColor;
|
||||
};
|
||||
const img = await ImagesCache.get(piecesStyle, type, color);
|
||||
const rank = flipped ? tiles - 1 - y : y;
|
||||
const file = flipped ? tiles - 1 - x : x;
|
||||
const { placement, check, mate, turn } = position;
|
||||
|
||||
const filters = [];
|
||||
for (const { x, y, type, color } of placement) {
|
||||
const img = await ImagesCache.get(piecesStyle, type, color);
|
||||
const rank = flipped ? 8 - 1 - y : y;
|
||||
const file = flipped ? 8 - 1 - x : x;
|
||||
|
||||
if (shadow) {
|
||||
filters.push(
|
||||
`drop-shadow(${squareSize * 0.05}px ${squareSize * 0.05}px ${
|
||||
squareSize * 0.05
|
||||
}px rgba(0, 0, 0, 0.6))`
|
||||
);
|
||||
}
|
||||
const filters = [];
|
||||
|
||||
// if ((color === check || color === mate) && type === "k") {
|
||||
// const hex = check ? "#ffa600" : "#ff002f";
|
||||
// drawCircle(
|
||||
// ctx,
|
||||
// squareSize / 2,
|
||||
// borderWidth + file * squareSize,
|
||||
// borderWidth + rank * squareSize + margin,
|
||||
// 0,
|
||||
// hex,
|
||||
// true
|
||||
// );
|
||||
// }
|
||||
// if ((color === check || color === mate) && type === "k") {
|
||||
// const hex = check ? "#ffa600" : "#ff002f";
|
||||
// drawCircle(
|
||||
// ctx,
|
||||
// squareSize / 2,
|
||||
// borderWidth + file * squareSize,
|
||||
// borderWidth + rank * squareSize + margin,
|
||||
// 0,
|
||||
// hex,
|
||||
// true
|
||||
// );
|
||||
// }
|
||||
|
||||
if ((color === check || color === mate) && type === "k") {
|
||||
const hex = check ? "#ffa600" : "#ff002f";
|
||||
filters.push(`drop-shadow(0 0 ${squareSize * 0.07}px ${hex})`);
|
||||
filters.push(`drop-shadow(0 0 ${squareSize * 0.07}px ${hex})`);
|
||||
}
|
||||
|
||||
ctx.filter = filters.length > 0 ? filters.join(" ") : "none";
|
||||
|
||||
ctx.drawImage(
|
||||
img,
|
||||
borderWidth + file * squareSize,
|
||||
borderWidth + rank * squareSize + margin,
|
||||
squareSize,
|
||||
squareSize
|
||||
);
|
||||
}
|
||||
if ((check || mate) && type === "k" && color === turn) {
|
||||
const hex = mate ? "#ff002f" : "#ffa600";
|
||||
filters.push(`drop-shadow(0 0 ${squareSize * 0.07}px ${hex})`);
|
||||
filters.push(`drop-shadow(0 0 ${squareSize * 0.07}px ${hex})`);
|
||||
}
|
||||
}
|
||||
|
||||
ctx.filter = "none";
|
||||
ctx.filter = filters.join(" ");
|
||||
|
||||
ctx.drawImage(
|
||||
img,
|
||||
borderWidth + file * squareSize,
|
||||
borderWidth + rank * squareSize + margin,
|
||||
squareSize,
|
||||
squareSize
|
||||
);
|
||||
|
||||
ctx.filter = "none";
|
||||
}
|
||||
};
|
||||
|
||||
export default drawPieces;
|
||||
|
||||
@@ -28,7 +28,7 @@ const style: Style = {
|
||||
border: {
|
||||
type: "solid",
|
||||
data: {
|
||||
color: "#40522f",
|
||||
color: "#312e2b",
|
||||
},
|
||||
},
|
||||
coords: {
|
||||
|
||||
Reference in New Issue
Block a user