Files
chess/frontend/main.js

179 lines
4.8 KiB
JavaScript

const BOX_SIDE = 80;
const INDEX_MARGIN = BOX_SIDE / 2;
const INDEX_LETTERS = 'abcdefgh';
function createCanvas() {
let canvas = document.createElement('canvas');
let boardSide = BOX_SIDE * 8 + INDEX_MARGIN;
canvas.width = boardSide;
canvas.height = boardSide;
document.body.appendChild(canvas);
return canvas
}
function drawChessBoard(canvas) {
let ctx = canvas.getContext('2d');
// Draw squares
ctx.fillStyle = '#c0c0c0';
for (let r = 0; r < 8; r++) {
for (let c = 0; c < 8; c++) {
if ((r + c) % 2) ctx.fillRect(c*BOX_SIDE + INDEX_MARGIN,
r*BOX_SIDE + INDEX_MARGIN,
BOX_SIDE, BOX_SIDE);
}
}
// Draw letters
ctx.fillStyle = 'black';
let fontsize = INDEX_MARGIN / 2;
ctx.font = `${fontsize}px Monospace`;
for (let idx = 0; idx < 8; idx++) {
ctx.fillText(INDEX_LETTERS[idx],
BOX_SIDE*idx + BOX_SIDE/2 + INDEX_MARGIN - fontsize / 4,
INDEX_MARGIN / 2);
ctx.fillText((8-idx).toString(),
INDEX_MARGIN / 2 - fontsize / 4,
BOX_SIDE*idx + BOX_SIDE/2 + INDEX_MARGIN + fontsize / 4);
}
}
function computeScreenCoords(position, canvas) {
let canvasRect = canvas.getBoundingClientRect();
let rc = boardIndexToRowCol(position);
let topPx = canvasRect.top + INDEX_MARGIN + rc[0]*BOX_SIDE + window.pageYOffset;
let leftPx = canvasRect.left + INDEX_MARGIN + rc[1]*BOX_SIDE + window.pageXOffset;
return [topPx, leftPx]
}
class Move {
constructor(kind, from, to) {
this.kind = kind;
this.from = from;
this.to = to;
}
}
class Piece {
constructor(who, color, position) {
this.who = who;
this.color = color;
this.position = position;
this._im = null;
}
icon() {
return `./icons/${this.who}_${this.color}.svg`
}
draw(canvas) {
let [topPx, leftPx] = computeScreenCoords(this.position, canvas);
if (this._im === null) {
let im = new Image(BOX_SIDE, BOX_SIDE);
im.src = this.icon();
im.onload = () => {
im.style.position = 'absolute';
im.style.top = `${topPx}px`;
im.style.left = `${leftPx}px`;
};
document.body.appendChild(im);
this._im = im;
}
else {
this._im.style.top = `${topPx}px`;
this._im.style.left = `${leftPx}px`;
}
}
undraw() {
if (this._im !== null) {
this._im.remove();
this._im = null;
}
}
}
class Configuration {
constructor(pieces) {
this.pieces = pieces
}
draw(canvas) {
for (let piece of this.pieces) {
piece.draw(canvas);
}
}
getAt(position) {
for (let piece of this.pieces) {
if (piece.position === position) return piece;
}
return null;
}
dropAt(position) {
for (let idx = 0; idx < this.pieces.length; idx++) {
if (this.pieces[idx].position === position) {
this.pieces[idx].undraw();
this.pieces.splice(idx, 1);
return;
}
}
}
makeMove(move, canvas) {
let piece = this.getAt(move.from);
if (piece === null) return;
this.dropAt(move.to);
piece.position = move.to;
piece.draw(canvas);
}
}
function setupBoard() {
let pawns = [];
for (let x of INDEX_LETTERS) {
pawns.push(new Piece('pawn', 'black', `${x}7`),
new Piece('pawn', 'white', `${x}2`));
}
return new Configuration([
new Piece('rook', 'black', 'a8'),
new Piece('rook', 'black', 'h8'),
new Piece('knight', 'black', 'b8'),
new Piece('knight', 'black', 'g8'),
new Piece('bishop', 'black', 'c8'),
new Piece('bishop', 'black', 'f8'),
new Piece('queen', 'black', 'd8'),
new Piece('king', 'black', 'e8'),
...pawns,
new Piece('rook', 'white', 'a1'),
new Piece('rook', 'white', 'h1'),
new Piece('knight', 'white', 'b1'),
new Piece('knight', 'white', 'g1'),
new Piece('bishop', 'white', 'c1'),
new Piece('bishop', 'white', 'f1'),
new Piece('queen', 'white', 'd1'),
new Piece('king', 'white', 'e1'),
])
}
function boardIndexToRowCol(boardIndex) {
let colLetter = boardIndex[0];
let rowDigit = boardIndex[1];
let row = 8 - parseInt(rowDigit);
let col = INDEX_LETTERS.indexOf(colLetter);
return [row, col];
}
async function demo() {
let canvas = createCanvas();
drawChessBoard(canvas);
let config = setupBoard();
config.draw(canvas);
await new Promise(r => setTimeout(r, 6000));
config.makeMove({'kind': 'xxx', 'from': 'e2', 'to': 'e4'}, canvas);
await new Promise(r => setTimeout(r, 2000));
config.makeMove({'kind': 'xxx', 'from': 'e7', 'to': 'e5'}, canvas);
await new Promise(r => setTimeout(r, 2000));
config.makeMove({'kind': 'xxx', 'from': 'd2', 'to': 'd4'}, canvas);
await new Promise(r => setTimeout(r, 2000));
config.makeMove({'kind': 'xxx', 'from': 'e5', 'to': 'd4'}, canvas);
}
demo();