From 555aad18e727e0e6b17e8de69217eee00125be08 Mon Sep 17 00:00:00 2001 From: "Stanislav Ch. Nikolov" Date: Wed, 23 Aug 2023 00:36:49 +0300 Subject: [PATCH] Replace chessboard-element with a custom canvas renderer for the main page --- frontend/canvas-chess-renderer.ts | 160 ++++++++++++++++++++++++++++++ frontend/index.ts | 74 ++++++++------ public/chess-pieces.png | Bin 0 -> 33280 bytes public/index.html | 6 +- 4 files changed, 210 insertions(+), 30 deletions(-) create mode 100644 frontend/canvas-chess-renderer.ts create mode 100644 public/chess-pieces.png diff --git a/frontend/canvas-chess-renderer.ts b/frontend/canvas-chess-renderer.ts new file mode 100644 index 0000000..dc023a0 --- /dev/null +++ b/frontend/canvas-chess-renderer.ts @@ -0,0 +1,160 @@ +const atlas = new Image(); +atlas.src = "/public/chess-pieces.png"; +const ASS = 240; // Atlas Sprite Size + +type PieceType = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11; +type Position = [ number, number ]; +type PieceAnimation = [PieceType , Position, Position | null]; + +export default class CanvasChessRenderer { + canvas: HTMLCanvasElement; + ctx: CanvasRenderingContext2D; + pieceAnimations: PieceAnimation[] = []; + animationBegin: number; + ANIMATION_LENGTH = 500; + animationRequest: number | null = null; + + constructor(canvas: HTMLCanvasElement) { + this.canvas = canvas; + this.ctx = this.canvas.getContext('2d')!; + this.resize(); + + const resizeObserver = new ResizeObserver(() => this.resize()); + resizeObserver.observe(canvas); + } + + resize() { + if (this.canvas.clientWidth === 0) { // Why is that needed? + console.log("refusing resize") + return; + } + this.canvas.width = this.canvas.clientWidth * window.devicePixelRatio; + this.canvas.height = this.canvas.clientHeight * window.devicePixelRatio; + this.#moarAnimationNeeded(); + } + + setPosition(fen: string) { + let idx = 0; + const newPieces: [PieceType, Position][] = []; + for(const c of fen.split(' ')[0]) { + if(c === '/') { continue; } + if(c === '1') { idx += 1; continue; } + if(c === '2') { idx += 2; continue; } + if(c === '3') { idx += 3; continue; } + if(c === '4') { idx += 4; continue; } + if(c === '5') { idx += 5; continue; } + if(c === '6') { idx += 6; continue; } + if(c === '7') { idx += 7; continue; } + if(c === '8') { idx += 8; continue; } + const pt = {p:0,P:1,n:2,N:3,b:4,B:5,r:6,R:7,q:8,Q:9,k:10,K:11}[c]; + newPieces.push([pt, [Math.floor(idx / 8), idx % 8]]); + idx += 1; + } + + // Match newPieces with this.pieces so that we know what moved where and animate + // properly. + const newPieceAnimations: PieceAnimation[] = []; + + // 0. Remove piece animations that are already done. + this.pieceAnimations = this.pieceAnimations.filter(([, , currPos]) => currPos != null); + + // 1. Match new pieces that didn't move at all. + for(let i = 0;i < newPieces.length;i ++) { + for(let j = 0;j < this.pieceAnimations.length;j ++) { + if (newPieces[i][0] !== this.pieceAnimations[j][0]) continue; + if (newPieces[i][1][0] !== this.pieceAnimations[j][2]![0]) continue; + if (newPieces[i][1][1] !== this.pieceAnimations[j][2]![1]) continue; + + // Matched i and j, yey! + newPieceAnimations.push([newPieces[i][0], newPieces[i][1], newPieces[i][1]]); + newPieces.splice(i, 1); + this.pieceAnimations.splice(j, 1); + i --; + break; + } + } + + // 2. Match new pieces that moved. + for(let i = 0;i < newPieces.length;i ++) { + for(let j = 0;j < this.pieceAnimations.length;j ++) { + if (newPieces[i][0] !== this.pieceAnimations[j][0]) continue; + + // Matched i and j, yey! + newPieceAnimations.push([newPieces[i][0], this.pieceAnimations[j][2]!, newPieces[i][1]]); + newPieces.splice(i, 1); + this.pieceAnimations.splice(j, 1); + i --; + break; + } + } + + // 3. Make brand new pieces appear. + for (const np of newPieces) { + newPieceAnimations.push([np[0], null, np[1]]); + } + + // 4. Make old pieces disappear. + for(const pa of this.pieceAnimations) { + newPieceAnimations.push([pa[0], pa[2]!, null]); + } + + this.animationBegin = Date.now(); + this.pieceAnimations = newPieceAnimations; + + this.#moarAnimationNeeded(); + } + + #moarAnimationNeeded() { + if (this.animationRequest != null) return; // Already animation requested. + this.animationRequest = window.requestAnimationFrame(() => this.#draw()); + } + + #draw() { + const drawSize = this.canvas.width / 8; + + let T = (Date.now() - this.animationBegin) / this.ANIMATION_LENGTH; + if (T > 1) T = 1; + // https://math.stackexchange.com/questions/121720/ease-in-out-function/121755#121755 + const animT = Math.pow(T, 3) / (Math.pow(T, 3) + Math.pow(1-T, 3)); + + // Draw the background checkerboard pattern. + this.ctx.fillStyle = '#b18a66'; + this.ctx.globalAlpha = 1; + this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height); + this.ctx.fillStyle = '#eedab8'; + for(let row = 0;row < 8; row ++) { + for(let col = 0;col < 8; col ++) { + if(row % 2 !== col % 2) continue; + this.ctx.fillRect(col * drawSize, row * drawSize, drawSize, drawSize); + } + } + + for(const [pt, lastPos, currPos] of this.pieceAnimations) { + let dx = 0, dy = 0; + if (currPos == null) { + // Animate by fading out. + this.ctx.globalAlpha = 1 - animT; + dy = lastPos[0]; + dx = lastPos[1]; + } else if (lastPos == null) { + // Animate by fading in. + this.ctx.globalAlpha = animT; + dy = currPos[0]; + dx = currPos[1]; + } else { + // Animate by moving the piece. + this.ctx.globalAlpha = 1; + dy = lastPos[0] + (currPos[0] - lastPos[0]) * animT; + dx = lastPos[1] + (currPos[1] - lastPos[1]) * animT; + } + + const cutX = Math.floor(pt / 2); + const cutY = pt % 2; // White pieces are on the top row of the atlas. + + this.ctx.drawImage(atlas, cutX * ASS, cutY * ASS, ASS, ASS, dx * drawSize, dy * drawSize, drawSize, drawSize); + } + + this.animationRequest = null; + if (T < 1) this.#moarAnimationNeeded(); + } +}; diff --git a/frontend/index.ts b/frontend/index.ts index 3cbd201..a266b83 100644 --- a/frontend/index.ts +++ b/frontend/index.ts @@ -1,4 +1,4 @@ -import "chessboard-element"; +import CanvasChessRenderer from './canvas-chess-renderer'; const $ = s => document.querySelector(s); @@ -8,13 +8,19 @@ function sanitizeHTML(text) { return element.innerHTML; } +function html2element(html: string) { + const template = document.createElement("template"); + template.innerHTML = html.trim(); + return template.content.firstChild as HTMLElement; +} + interface MyBots { id?: number; name?: string; email?: string; bots: number[]; } -let globalMyBots: MyBots = { id: null, name: null, bots: [] }; +let globalMyBots: MyBots = { bots: [] }; interface Dev { id: number; @@ -32,6 +38,19 @@ interface OldGame { reason: string; }; +interface LiveGame { + id: number; + wid: number; + wname: string; + welo: number; + bid: number; + bname: string; + belo: number; + initial_position: string; + fen: string; +}; +const livesGames: Record = []; + interface Bot { id: number; name: string; @@ -72,7 +91,7 @@ function renderEditableLeaderboardItem(place: number, name: string, elo: number, `; } -function renderOldGame(g: OldGame) { +function renderOldGame(g: OldGame): HTMLElement { return ` @@ -87,11 +106,11 @@ function renderOldGame(g: OldGame) { `; } -function renderLiveGame(g) { +function renderLiveGame(g: LiveGame) { return ` -
+
${sanitizeHTML(g.bname)} ${g.belo.toFixed(0)}
- +
${sanitizeHTML(g.wname)} ${g.welo.toFixed(0)}
`; @@ -137,41 +156,39 @@ async function updateOldGames() { } async function updateLiveGames() { - const req = await fetch('/api/live-games/') - const games = await req.json(); + const req = await fetch("https://chess.stjo.dev/api/live-games/") + const games = await req.json() as LiveGame[]; - for (const drawnGame of document.querySelectorAll("[data-game-id]")) { - const gameId = Number(drawnGame.getAttribute("data-game-id")); - if (!games.find(g => g.id === gameId)) drawnGame.removeAttribute("data-game-id"); + for (const gameId in livesGames) { + if (games.find(g => g.id === Number(gameId))) continue; + livesGames[gameId].el.classList.remove("used"); + delete livesGames[gameId]; } for (const g of games) { - const existingEl = document.querySelector(`[data-game-id="${g.id}"]`); - // Try to update the already rendered board. - if (existingEl) { - existingEl.querySelector('chess-board')!.setPosition(g.fen); + const existingGame = livesGames[g.id]; + if (existingGame) { + existingGame.ccr.setPosition(g.fen); continue; } - // Try to find an empty board to connect to - we do that to minimize the flashes - const candidate = document.querySelector(".live-game:not([data-game-id])"); + // Try to find an empty board to "connect to" - we do that to minimize the flashes + const candidate = $(".live-game:not(.used)"); if (candidate) { - candidate.outerHTML = renderLiveGame(g); + const newEl = html2element(renderLiveGame(g)); + candidate.replaceWith(newEl); + const canvas = newEl.querySelector('canvas')!; + livesGames[g.id] = { el: newEl, ccr: new CanvasChessRenderer(canvas) }; continue; } // Last resort - make a new square. - $('#live-games').innerHTML += renderLiveGame(g); + const el = html2element(renderLiveGame(g)); + $('#live-games').appendChild(el); + console.log(el); + livesGames[g.id] = { el, ccr: new CanvasChessRenderer(el.querySelector('canvas')!) }; } - // There is a bug with the chess-board library. It has an element - // taking space that shouldn't exist. - setTimeout(() => { - for (const cb of document.querySelectorAll('chess-board')) { - cb.shadowRoot.querySelector('#dragged-pieces')?.remove(); - } - }, 0); - setTimeout(updateLiveGames, 500); }; @@ -195,14 +212,13 @@ async function updateMyBots() { } } - updateMyBots(); updateLiveGames(); updateOldGames(); updateDevLeaderboard(); updateBotLeaderboard(); -$("#timer-content").innerHTML = ((new Date('2023-10-01') - new Date()) / (1000 * 60 * 60 * 24)).toFixed(0); +$("#timer-content").innerHTML = ((new Date('2023-10-01').getTime() - Date.now()) / (1000 * 60 * 60 * 24)).toFixed(0); $("#open-upload-dialog").addEventListener("click", () => { $("#compilation-message").classList.toggle('hidden', true); diff --git a/public/chess-pieces.png b/public/chess-pieces.png new file mode 100644 index 0000000000000000000000000000000000000000..4ea5dd53d05e4020af7abbd60116f68200a5e54d GIT binary patch literal 33280 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
!D0n%f-uLqLJ8K3l5Zn1f8aUznc^C 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 literal 0 HcmV?d00001 diff --git a/public/index.html b/public/index.html index d88423a..8aa53e4 100644 --- a/public/index.html +++ b/public/index.html @@ -180,8 +180,12 @@ grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); overflow-y: auto; } +canvas { + aspect-ratio: 1; + width: 100%; +} -.live-game:not([data-game-id]) { +.live-game:not(.used) { opacity: 0; }