This commit is contained in:
Maciej Caderek
2022-01-18 06:45:22 +01:00
parent 2214e73ad4
commit 8a3743a328
9 changed files with 150 additions and 74 deletions

View File

@@ -5,6 +5,7 @@ import drawBorder from "./layers/drawBorder";
import drawCoords from "./layers/drawCoords"; import drawCoords from "./layers/drawCoords";
import drawMoveIndicators from "./layers/drawMoveIndicators"; import drawMoveIndicators from "./layers/drawMoveIndicators";
import drawPieces from "./layers/drawPieces"; import drawPieces from "./layers/drawPieces";
import drawHeader from "./layers/drawHeader.ts";
import boards from "./styles-board"; import boards from "./styles-board";
class Board { class Board {
@@ -18,6 +19,11 @@ class Board {
private lastMove: Move | null = null; private lastMove: Move | null = null;
public canvas: HTMLCanvasElement = document.createElement("canvas"); public canvas: HTMLCanvasElement = document.createElement("canvas");
private tempCanvas: HTMLCanvasElement = document.createElement("canvas"); private tempCanvas: HTMLCanvasElement = document.createElement("canvas");
private squareSize: number = 84;
private innerSize: number = 672;
private borderWidth: number = 24;
private background: Promise<ImageBitmap> | null = null;
// private frames: Promise<ImageBitmap>[] = [];
constructor(private tiles: number = 8) { constructor(private tiles: number = 8) {
const ctx = this.canvas.getContext("2d"); const ctx = this.canvas.getContext("2d");
@@ -39,6 +45,13 @@ class Board {
this.canvas.height = size; this.canvas.height = size;
this.tempCanvas.width = size; this.tempCanvas.width = size;
this.tempCanvas.height = size; this.tempCanvas.height = size;
const tempBorderWidth = this.borderVisible ? this.size / 32 : 0;
const tempInnerSize = this.size - tempBorderWidth * 2;
this.squareSize = Math.floor(tempInnerSize / this.tiles);
this.innerSize = this.squareSize * this.tiles;
this.borderWidth = (this.size - this.innerSize) / 2;
return this; return this;
} }
@@ -59,11 +72,13 @@ class Board {
hideBorder() { hideBorder() {
this.borderVisible = false; this.borderVisible = false;
this.setSize(this.size);
return this; return this;
} }
showBorder() { showBorder() {
this.borderVisible = true; this.borderVisible = true;
this.setSize(this.size);
return this; return this;
} }
@@ -92,49 +107,28 @@ class Board {
} }
async renderTitleScreen(header: { [key: string]: string | undefined }) { async renderTitleScreen(header: { [key: string]: string | undefined }) {
console.log(header); await drawHeader(this.tempCtx, this.size, this.style, header);
this.tempCtx.clearRect(0, 0, this.size, this.size);
await drawSquare(this.tempCtx, this.size, 0, 0, this.style.border);
this.ctx.drawImage(this.tempCanvas, 0, 0); this.ctx.drawImage(this.tempCanvas, 0, 0);
} }
async render(boardData: BoardData | null, move: Move | null = null) { async renderBackground() {
this.lastMove = move;
this.boardData = boardData;
const { background, dark, light, border, coords } = this.style; const { background, dark, light, border, coords } = this.style;
const hasBorder = border && this.borderVisible;
const tempBorderWidth = hasBorder ? this.size / 32 : 0;
const tempInnerSize = this.size - tempBorderWidth * 2;
const squareSize = Math.floor(tempInnerSize / this.tiles);
const innerSize = squareSize * this.tiles;
const borderWidth = (this.size - innerSize) / 2;
const check = this.isCheck(move)
? this.getOppositeColor(move?.color)
: undefined;
const mate = this.isMate(move)
? this.getOppositeColor(move?.color)
: undefined;
this.tempCtx.clearRect(0, 0, this.size, this.size);
await drawSquare( await drawSquare(
this.tempCtx, this.tempCtx,
innerSize, this.innerSize,
borderWidth, this.borderVisible ? this.borderWidth : 0,
borderWidth, this.borderVisible ? this.borderWidth : 0,
background background
); );
if (hasBorder) { if (this.borderVisible) {
await drawBorder( await drawBorder(
this.tempCtx, this.tempCtx,
this.size - borderWidth, this.size - this.borderWidth,
borderWidth / 2, this.borderWidth / 2,
borderWidth / 2, this.borderWidth / 2,
borderWidth, this.borderWidth,
border border
); );
} }
@@ -147,31 +141,54 @@ class Board {
? light ? light
: dark; : dark;
const x = file * squareSize + borderWidth; const x = file * this.squareSize + this.borderWidth;
const y = rank * squareSize + borderWidth; const y = rank * this.squareSize + this.borderWidth;
await drawSquare(this.tempCtx, squareSize, x, y, style); await drawSquare(this.tempCtx, this.squareSize, x, y, style);
} }
} }
drawCoords( drawCoords(
this.tempCtx, this.tempCtx,
coords, coords,
squareSize, this.squareSize,
this.tiles, this.tiles,
this.flipped, this.flipped,
borderWidth, this.borderWidth,
this.size this.size,
this.borderVisible
); );
this.background = createImageBitmap(this.tempCanvas);
}
async render(boardData: BoardData | null, move: Move | null = null) {
this.lastMove = move;
this.boardData = boardData;
const check = this.isCheck(move)
? this.getOppositeColor(move?.color)
: undefined;
const mate = this.isMate(move)
? this.getOppositeColor(move?.color)
: undefined;
this.tempCtx.clearRect(0, 0, this.size, this.size);
if (this.background === null) {
await this.renderBackground();
}
this.tempCtx.drawImage((await this.background) as ImageBitmap, 0, 0);
if (boardData !== null) { if (boardData !== null) {
if (this.lastMove) { if (this.lastMove) {
drawMoveIndicators( drawMoveIndicators(
this.tempCtx, this.tempCtx,
this.lastMove, this.lastMove,
squareSize, this.squareSize,
this.style, this.style,
borderWidth, this.borderWidth,
this.tiles, this.tiles,
this.flipped this.flipped
); );
@@ -180,8 +197,8 @@ class Board {
await drawPieces( await drawPieces(
this.tempCtx, this.tempCtx,
boardData, boardData,
squareSize, this.squareSize,
borderWidth, this.borderWidth,
this.tiles, this.tiles,
this.flipped, this.flipped,
check, check,

View File

@@ -10,7 +10,8 @@ const drawCoords = (
tiles: number, tiles: number,
blackSide: boolean = false, blackSide: boolean = false,
borderWidth: number, borderWidth: number,
size: number size: number,
hasBorder: boolean
) => { ) => {
const scale = size / 1024; const scale = size / 1024;
@@ -19,16 +20,8 @@ const drawCoords = (
} }
const fontSize = BASE_FONT_SIZE * scale; const fontSize = BASE_FONT_SIZE * scale;
const offset = 10; const offsetA = 6 * scale;
const offsetFileX = const offsetB = 4 * scale;
borderWidth > 0 ? borderWidth + squareSize / 2 : offset * scale;
const offsetFileY =
borderWidth > 0 ? -borderWidth * 2 + offset * scale : offset * scale;
const offsetRankX = borderWidth > 0 ? borderWidth / 2 : offset * scale;
const offsetRankY =
borderWidth > 0
? borderWidth + squareSize / 2 - fontSize / 2
: offset * scale;
const ranks = const ranks =
"1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26" "1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26"
@@ -37,6 +30,7 @@ const drawCoords = (
const orderedRanks = blackSide ? ranks : ranks.reverse(); const orderedRanks = blackSide ? ranks : ranks.reverse();
ctx.font = `${fontSize}px ${FONT_FAMILY}`; ctx.font = `${fontSize}px ${FONT_FAMILY}`;
ctx.textBaseline = hasBorder ? "middle" : "top";
orderedRanks.forEach((v, i) => { orderedRanks.forEach((v, i) => {
ctx.fillStyle = ctx.fillStyle =
@@ -46,13 +40,20 @@ const drawCoords = (
? coords.onLight ? coords.onLight
: coords.onDark; : coords.onDark;
ctx.textAlign = borderWidth > 0 ? "center" : "left"; const x = hasBorder ? borderWidth / 2 : offsetA;
ctx.fillText(v, offsetRankX, squareSize * i + fontSize + offsetRankY); const y = hasBorder
? squareSize * i + borderWidth + squareSize / 2
: squareSize * i + offsetA;
ctx.textAlign = hasBorder ? "center" : "left";
ctx.fillText(v, x, y);
}); });
const files = "ABCDEFGHIJKLMNOPQRSTUWVXYZ".split("").slice(0, tiles); const files = "ABCDEFGHIJKLMNOPQRSTUWVXYZ".split("").slice(0, tiles);
const orderedFiles = blackSide ? files.reverse() : files; const orderedFiles = blackSide ? files.reverse() : files;
ctx.textBaseline = hasBorder ? "middle" : "bottom";
orderedFiles.forEach((v, i) => { orderedFiles.forEach((v, i) => {
ctx.fillStyle = ctx.fillStyle =
borderWidth > 0 borderWidth > 0
@@ -61,12 +62,13 @@ const drawCoords = (
? coords.onDark ? coords.onDark
: coords.onLight; : coords.onLight;
ctx.textAlign = borderWidth > 0 ? "center" : "left"; const x = hasBorder
ctx.fillText( ? squareSize * i + borderWidth + squareSize / 2
v, : squareSize * i + offsetA;
squareSize * i + offsetFileX, const y = hasBorder ? size - borderWidth / 2 : size - offsetB;
squareSize * tiles - offsetFileY
); ctx.textAlign = hasBorder ? "center" : "left";
ctx.fillText(v, x, y);
}); });
}; };

View File

@@ -0,0 +1,54 @@
import { Style } from "./../../types";
import drawSquare from "../layers/drawSquare";
const drawText = (
ctx: CanvasRenderingContext2D,
text: string,
fontSize: number,
x: number,
y: number,
align: CanvasTextAlign
) => {
ctx.font = `${fontSize}px Arial`;
ctx.textAlign = align;
ctx.textBaseline = "middle";
ctx.fillText(text, x, y);
};
const drawHeader = async (
ctx: CanvasRenderingContext2D,
size: number,
style: Style,
data: { [key: string]: string | undefined }
) => {
console.log(data);
const scale = size / 720;
ctx.clearRect(0, 0, size, size);
await drawSquare(ctx, size, 0, 0, style.border);
ctx.fillStyle = style.coords.onBorder;
if (data.White) {
drawText(ctx, data.White, 36 * scale, size / 2, 200 * scale, "center");
}
drawText(ctx, "vs", 20 * scale, size / 2, 260 * scale, "center");
if (data.Black) {
drawText(ctx, data.Black, 36 * scale, size / 2, 320 * scale, "center");
}
if (data.Date) {
drawText(ctx, data.Date, 20 * scale, size / 2, 500 * scale, "center");
}
if (data.Event) {
drawText(ctx, data.Event, 24 * scale, size / 2, 540 * scale, "center");
}
if (data.Site) {
drawText(ctx, data.Site, 20 * scale, size / 2, 580 * scale, "center");
}
};
export default drawHeader;

View File

@@ -19,7 +19,7 @@ const drawPieces = async (
type: PieceType; type: PieceType;
color: PieceColor; color: PieceColor;
}; };
const img = await ImagesCache.get("cburnett", type, color); const img = await ImagesCache.get("tatiana", type, color);
const rank = flipped ? tiles - 1 - y : y; const rank = flipped ? tiles - 1 - y : y;
const file = flipped ? tiles - 1 - x : x; const file = flipped ? tiles - 1 - x : x;

View File

@@ -31,8 +31,8 @@ const style: Style = {
}, },
}, },
coords: { coords: {
onLight: "#72b339", onLight: "#4d7a26",
onDark: "#ececa4", onDark: "#ffffc4",
onBorder: "#ececa4", onBorder: "#ececa4",
}, },
}; };

View File

@@ -31,8 +31,8 @@ const style: Style = {
}, },
}, },
coords: { coords: {
onLight: "#c0acb5", onLight: "#876b77",
onDark: "#e5d0cb", onDark: "#fff5f2",
onBorder: "#e5d0cb", onBorder: "#e5d0cb",
}, },
}; };

View File

@@ -79,7 +79,7 @@ class Game {
} }
getHeader() { getHeader() {
return this.replay.header(); return this.game.header();
} }
pgn() { pgn() {

View File

@@ -14,6 +14,9 @@ const createSimpleGIF = async (
const board = new Board(8).setStyle(style).setSize(size).showBorder(); const board = new Board(8).setStyle(style).setSize(size).showBorder();
const gif = new GIF(size, true); const gif = new GIF(size, true);
await board.renderTitleScreen(game.getHeader());
gif.add(board.toImgElement(), 5000);
await board.render(game.getBoardData()); await board.render(game.getBoardData());
gif.add(board.toImgElement(), MOVE_TIME); gif.add(board.toImgElement(), MOVE_TIME);

View File

@@ -3,7 +3,7 @@ import "./style.css";
import Board from "./board/Board"; import Board from "./board/Board";
import styles from "./board/styles-board"; import styles from "./board/styles-board";
import Game from "./game/Game"; import Game from "./game/Game";
// import pgns from "./test-data/pgns"; import pgns from "./test-data/pgns";
import createSimpleGIF from "./gif/createSimpleGIF"; import createSimpleGIF from "./gif/createSimpleGIF";
import { decompressPGN } from "./game/PGNHelpers"; import { decompressPGN } from "./game/PGNHelpers";
@@ -19,8 +19,8 @@ const play = async (board: Board, pgn: string | null, interval: number) => {
} }
// game.goto(28); // game.goto(28);
// await board.renderTitleScreen(game.getHeader()); await board.renderTitleScreen(game.getHeader());
// await delay(interval); await delay(interval * 5);
await board.render(game.getBoardData()); await board.render(game.getBoardData());
while (true) { while (true) {
@@ -50,7 +50,7 @@ const createDownloadLink = async (pgn: string, style: Style) => {
console.log(createDownloadLink.name); console.log(createDownloadLink.name);
const main = async () => { const main = async () => {
const style = styles.avocado; const style = styles.lila;
window.location.hash = window.location.hash =
"#QiBEdWtlIEthcmwgLyBDb3VudCBJc291YXJkCkQgMTg1OC4/Py4/PwpFIFBhcmlzClIgMS0wClMgUGFyaXMgRlJBClcgUGF1bCBNb3JwaHkKCmU0IGU1IE5mMyBkNiBkNCBCZzQgZHhlNSBCeGYzIFF4ZjMgZHhlNSBCYzQgTmY2IFFiMyBRZTcgTmMzIGM2IEJnNSBiNSBOeGI1IGN4YjUgQnhiNSsgTmJkNyBPLU8tTyBSZDggUnhkNyBSeGQ3IFJkMSBRZTYgQnhkNysgTnhkNyBRYjgrIE54YjggUmQ4Iw=="; "#QiBEdWtlIEthcmwgLyBDb3VudCBJc291YXJkCkQgMTg1OC4/Py4/PwpFIFBhcmlzClIgMS0wClMgUGFyaXMgRlJBClcgUGF1bCBNb3JwaHkKCmU0IGU1IE5mMyBkNiBkNCBCZzQgZHhlNSBCeGYzIFF4ZjMgZHhlNSBCYzQgTmY2IFFiMyBRZTcgTmMzIGM2IEJnNSBiNSBOeGI1IGN4YjUgQnhiNSsgTmJkNyBPLU8tTyBSZDggUnhkNyBSeGQ3IFJkMSBRZTYgQnhkNysgTnhkNyBRYjgrIE54YjggUmQ4Iw==";
@@ -63,11 +63,11 @@ const main = async () => {
console.log(pgn); console.log(pgn);
play(board, pgn, 1000); play(board, pgns[2], 1000);
// createDownloadLink(pgns[0], style).then((link) => { createDownloadLink(pgns[2], style).then((link) => {
// document.body.appendChild(link); document.body.appendChild(link);
// }); });
}; };
main(); main();