WIP
This commit is contained in:
@@ -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,
|
||||||
|
|||||||
@@ -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);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
54
src/board/layers/drawHeader.ts.ts
Normal file
54
src/board/layers/drawHeader.ts.ts
Normal 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;
|
||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -31,8 +31,8 @@ const style: Style = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
coords: {
|
coords: {
|
||||||
onLight: "#72b339",
|
onLight: "#4d7a26",
|
||||||
onDark: "#ececa4",
|
onDark: "#ffffc4",
|
||||||
onBorder: "#ececa4",
|
onBorder: "#ececa4",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -31,8 +31,8 @@ const style: Style = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
coords: {
|
coords: {
|
||||||
onLight: "#c0acb5",
|
onLight: "#876b77",
|
||||||
onDark: "#e5d0cb",
|
onDark: "#fff5f2",
|
||||||
onBorder: "#e5d0cb",
|
onBorder: "#e5d0cb",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ class Game {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getHeader() {
|
getHeader() {
|
||||||
return this.replay.header();
|
return this.game.header();
|
||||||
}
|
}
|
||||||
|
|
||||||
pgn() {
|
pgn() {
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
16
src/main.ts
16
src/main.ts
@@ -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();
|
||||||
|
|||||||
Reference in New Issue
Block a user