From 8a3743a3281426dc26cfb5c2d1ad683bf6238c50 Mon Sep 17 00:00:00 2001 From: Maciej Caderek Date: Tue, 18 Jan 2022 06:45:22 +0100 Subject: [PATCH] WIP --- src/board/Board.ts | 99 ++++++++++++++++++------------- src/board/layers/drawCoords.ts | 40 +++++++------ src/board/layers/drawHeader.ts.ts | 54 +++++++++++++++++ src/board/layers/drawPieces.ts | 2 +- src/board/styles-board/avocado.ts | 4 +- src/board/styles-board/lila.ts | 4 +- src/game/Game.ts | 2 +- src/gif/createSimpleGIF.ts | 3 + src/main.ts | 16 ++--- 9 files changed, 150 insertions(+), 74 deletions(-) create mode 100644 src/board/layers/drawHeader.ts.ts diff --git a/src/board/Board.ts b/src/board/Board.ts index 91edc60..55aea45 100644 --- a/src/board/Board.ts +++ b/src/board/Board.ts @@ -5,6 +5,7 @@ import drawBorder from "./layers/drawBorder"; import drawCoords from "./layers/drawCoords"; import drawMoveIndicators from "./layers/drawMoveIndicators"; import drawPieces from "./layers/drawPieces"; +import drawHeader from "./layers/drawHeader.ts"; import boards from "./styles-board"; class Board { @@ -18,6 +19,11 @@ class Board { private lastMove: Move | null = null; public canvas: 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 | null = null; + // private frames: Promise[] = []; constructor(private tiles: number = 8) { const ctx = this.canvas.getContext("2d"); @@ -39,6 +45,13 @@ class Board { this.canvas.height = size; this.tempCanvas.width = 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; } @@ -59,11 +72,13 @@ class Board { hideBorder() { this.borderVisible = false; + this.setSize(this.size); return this; } showBorder() { this.borderVisible = true; + this.setSize(this.size); return this; } @@ -92,49 +107,28 @@ class Board { } async renderTitleScreen(header: { [key: string]: string | undefined }) { - console.log(header); - this.tempCtx.clearRect(0, 0, this.size, this.size); - await drawSquare(this.tempCtx, this.size, 0, 0, this.style.border); - + await drawHeader(this.tempCtx, this.size, this.style, header); this.ctx.drawImage(this.tempCanvas, 0, 0); } - async render(boardData: BoardData | null, move: Move | null = null) { - this.lastMove = move; - this.boardData = boardData; + async renderBackground() { 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( this.tempCtx, - innerSize, - borderWidth, - borderWidth, + this.innerSize, + this.borderVisible ? this.borderWidth : 0, + this.borderVisible ? this.borderWidth : 0, background ); - if (hasBorder) { + if (this.borderVisible) { await drawBorder( this.tempCtx, - this.size - borderWidth, - borderWidth / 2, - borderWidth / 2, - borderWidth, + this.size - this.borderWidth, + this.borderWidth / 2, + this.borderWidth / 2, + this.borderWidth, border ); } @@ -147,31 +141,54 @@ class Board { ? light : dark; - const x = file * squareSize + borderWidth; - const y = rank * squareSize + borderWidth; + const x = file * this.squareSize + this.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( this.tempCtx, coords, - squareSize, + this.squareSize, this.tiles, this.flipped, - borderWidth, - this.size + this.borderWidth, + 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 (this.lastMove) { drawMoveIndicators( this.tempCtx, this.lastMove, - squareSize, + this.squareSize, this.style, - borderWidth, + this.borderWidth, this.tiles, this.flipped ); @@ -180,8 +197,8 @@ class Board { await drawPieces( this.tempCtx, boardData, - squareSize, - borderWidth, + this.squareSize, + this.borderWidth, this.tiles, this.flipped, check, diff --git a/src/board/layers/drawCoords.ts b/src/board/layers/drawCoords.ts index 8ec133c..5a8893b 100644 --- a/src/board/layers/drawCoords.ts +++ b/src/board/layers/drawCoords.ts @@ -10,7 +10,8 @@ const drawCoords = ( tiles: number, blackSide: boolean = false, borderWidth: number, - size: number + size: number, + hasBorder: boolean ) => { const scale = size / 1024; @@ -19,16 +20,8 @@ const drawCoords = ( } const fontSize = BASE_FONT_SIZE * scale; - const offset = 10; - const offsetFileX = - 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 offsetA = 6 * scale; + const offsetB = 4 * scale; 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" @@ -37,6 +30,7 @@ const drawCoords = ( const orderedRanks = blackSide ? ranks : ranks.reverse(); ctx.font = `${fontSize}px ${FONT_FAMILY}`; + ctx.textBaseline = hasBorder ? "middle" : "top"; orderedRanks.forEach((v, i) => { ctx.fillStyle = @@ -46,13 +40,20 @@ const drawCoords = ( ? coords.onLight : coords.onDark; - ctx.textAlign = borderWidth > 0 ? "center" : "left"; - ctx.fillText(v, offsetRankX, squareSize * i + fontSize + offsetRankY); + const x = hasBorder ? borderWidth / 2 : offsetA; + 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 orderedFiles = blackSide ? files.reverse() : files; + ctx.textBaseline = hasBorder ? "middle" : "bottom"; + orderedFiles.forEach((v, i) => { ctx.fillStyle = borderWidth > 0 @@ -61,12 +62,13 @@ const drawCoords = ( ? coords.onDark : coords.onLight; - ctx.textAlign = borderWidth > 0 ? "center" : "left"; - ctx.fillText( - v, - squareSize * i + offsetFileX, - squareSize * tiles - offsetFileY - ); + const x = hasBorder + ? squareSize * i + borderWidth + squareSize / 2 + : squareSize * i + offsetA; + const y = hasBorder ? size - borderWidth / 2 : size - offsetB; + + ctx.textAlign = hasBorder ? "center" : "left"; + ctx.fillText(v, x, y); }); }; diff --git a/src/board/layers/drawHeader.ts.ts b/src/board/layers/drawHeader.ts.ts new file mode 100644 index 0000000..29aa1e0 --- /dev/null +++ b/src/board/layers/drawHeader.ts.ts @@ -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; diff --git a/src/board/layers/drawPieces.ts b/src/board/layers/drawPieces.ts index f09f04d..cbc24b0 100644 --- a/src/board/layers/drawPieces.ts +++ b/src/board/layers/drawPieces.ts @@ -19,7 +19,7 @@ const drawPieces = async ( type: PieceType; 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 file = flipped ? tiles - 1 - x : x; diff --git a/src/board/styles-board/avocado.ts b/src/board/styles-board/avocado.ts index d45faa2..1e3d589 100644 --- a/src/board/styles-board/avocado.ts +++ b/src/board/styles-board/avocado.ts @@ -31,8 +31,8 @@ const style: Style = { }, }, coords: { - onLight: "#72b339", - onDark: "#ececa4", + onLight: "#4d7a26", + onDark: "#ffffc4", onBorder: "#ececa4", }, }; diff --git a/src/board/styles-board/lila.ts b/src/board/styles-board/lila.ts index 0f41531..26aefd3 100644 --- a/src/board/styles-board/lila.ts +++ b/src/board/styles-board/lila.ts @@ -31,8 +31,8 @@ const style: Style = { }, }, coords: { - onLight: "#c0acb5", - onDark: "#e5d0cb", + onLight: "#876b77", + onDark: "#fff5f2", onBorder: "#e5d0cb", }, }; diff --git a/src/game/Game.ts b/src/game/Game.ts index 838bc48..4fce2e5 100644 --- a/src/game/Game.ts +++ b/src/game/Game.ts @@ -79,7 +79,7 @@ class Game { } getHeader() { - return this.replay.header(); + return this.game.header(); } pgn() { diff --git a/src/gif/createSimpleGIF.ts b/src/gif/createSimpleGIF.ts index f07c505..d2ba491 100644 --- a/src/gif/createSimpleGIF.ts +++ b/src/gif/createSimpleGIF.ts @@ -14,6 +14,9 @@ const createSimpleGIF = async ( const board = new Board(8).setStyle(style).setSize(size).showBorder(); const gif = new GIF(size, true); + await board.renderTitleScreen(game.getHeader()); + gif.add(board.toImgElement(), 5000); + await board.render(game.getBoardData()); gif.add(board.toImgElement(), MOVE_TIME); diff --git a/src/main.ts b/src/main.ts index c921f42..b264688 100644 --- a/src/main.ts +++ b/src/main.ts @@ -3,7 +3,7 @@ import "./style.css"; import Board from "./board/Board"; import styles from "./board/styles-board"; import Game from "./game/Game"; -// import pgns from "./test-data/pgns"; +import pgns from "./test-data/pgns"; import createSimpleGIF from "./gif/createSimpleGIF"; import { decompressPGN } from "./game/PGNHelpers"; @@ -19,8 +19,8 @@ const play = async (board: Board, pgn: string | null, interval: number) => { } // game.goto(28); - // await board.renderTitleScreen(game.getHeader()); - // await delay(interval); + await board.renderTitleScreen(game.getHeader()); + await delay(interval * 5); await board.render(game.getBoardData()); while (true) { @@ -50,7 +50,7 @@ const createDownloadLink = async (pgn: string, style: Style) => { console.log(createDownloadLink.name); const main = async () => { - const style = styles.avocado; + const style = styles.lila; window.location.hash = "#QiBEdWtlIEthcmwgLyBDb3VudCBJc291YXJkCkQgMTg1OC4/Py4/PwpFIFBhcmlzClIgMS0wClMgUGFyaXMgRlJBClcgUGF1bCBNb3JwaHkKCmU0IGU1IE5mMyBkNiBkNCBCZzQgZHhlNSBCeGYzIFF4ZjMgZHhlNSBCYzQgTmY2IFFiMyBRZTcgTmMzIGM2IEJnNSBiNSBOeGI1IGN4YjUgQnhiNSsgTmJkNyBPLU8tTyBSZDggUnhkNyBSeGQ3IFJkMSBRZTYgQnhkNysgTnhkNyBRYjgrIE54YjggUmQ4Iw=="; @@ -63,11 +63,11 @@ const main = async () => { console.log(pgn); - play(board, pgn, 1000); + play(board, pgns[2], 1000); - // createDownloadLink(pgns[0], style).then((link) => { - // document.body.appendChild(link); - // }); + createDownloadLink(pgns[2], style).then((link) => { + document.body.appendChild(link); + }); }; main();