This commit is contained in:
Maciej Caderek
2022-02-01 00:08:15 +01:00
parent 6ca3836586
commit 013796a2ed
17 changed files with 433 additions and 571 deletions

View File

@@ -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
);
}
}

View File

@@ -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;
}
}
};

View File

@@ -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;

View File

@@ -28,7 +28,7 @@ const style: Style = {
border: {
type: "solid",
data: {
color: "#40522f",
color: "#312e2b",
},
},
coords: {