// 地图宽高 8/ 8 +河界
// 格子
import {c} from "vite/dist/node/types.d-aGj9QkWt";
const lattice = 100;
const map = {
width: lattice * 8,
height: lattice * 8 + 100,
}
// 每个格子大小
class Chess {
private canvas: HTMLCanvasElement;
private width: number;
private height: number;
private ctx: CanvasRenderingContext2D;
private initKios = ["車", "馬", "象", "士", "将", "士", "象", "馬", "車", "炮", "兵", "卒", "帅"]
// 红方
private redKiko: Kiko[] = []
// 黑方
private blackKiko: Kiko[] = []
// 棋子画布
private kikoCanvas: HTMLCanvasElement;
private kikoCanvasCtx: CanvasRenderingContext2D;
// 先手 // 默认红方
private isStatus: ColorType = ColorType.RED;
// 当前选中棋子
private currentKiko: Kiko;
constructor(canvas: HTMLCanvasElement) {
this.canvas = canvas;
this.ctx = this.canvas.getContext("2d")!;
this.init();
}
init() {
const {clientWidth, clientHeight} = document.documentElement;
this.width = clientWidth;
this.height = clientHeight;
this.canvas.width = this.width;
this.canvas.height = this.height;
this.ctx.translate(100, 50)
this.createCanvas();
this.drawMap();
this.drawKiKos();
}
createCanvas() {
if (this.kikoCanvas) return;
const newCanvas = document.createElement("canvas");
this.kikoCanvas = newCanvas;
newCanvas.width = map.width + 100;
newCanvas.height = map.height + 150;
newCanvas.style.position = "absolute";
newCanvas.style.left = "550px";
newCanvas.style.top = "-10px";
newCanvas.style.width = map.width + 100 + "px";
newCanvas.style.height = map.height + 150 + "px";
// newCanvas.style.background="red";
// this.canvas.appendChild(newCanvas);
this.canvas.parentNode!.appendChild(newCanvas)
this.kikoCanvasCtx = this.kikoCanvas.getContext("2d")!;
this.kikoCanvasCtx.translate(50, 50)
this.kikoCanvas.addEventListener("mousedown", e => {
// 拿到坐标
const {clientX, clientY} = e;
const {x,y} = {
x:clientX - this.kikoCanvas.offsetLeft - 50,
y:clientY - this.kikoCanvas.offsetTop - 60
}
if(!this.currentKiko){
console.log(clientX - this.kikoCanvas.offsetLeft - 50, clientY - this.kikoCanvas.offsetTop - 60)
//是红方还是黑方
const item = this.getCheckKiko(x,y);
if(item){
this.currentKiko = item!;
}
console.log(item)
}else {
this.currentKiko.move(x,y);
Kiko.drawKiko(this.redKiko);
Kiko.drawKiko(this.blackKiko);
this.currentKiko = undefined;
}
})
}
//画地图
drawMap() {
// this.ctx.strokeStyle="red"
this.ctx.lineWidth = 2
this.ctx.beginPath();
this.ctx.moveTo(500, 20);
this.ctx.lineTo(500 + map.width, 20);
this.ctx.lineTo(500 + map.width, 20 + map.height);
this.ctx.lineTo(500, 20 + map.height)
this.ctx.lineTo(500, 20);
for (let i = 0; i < 8; i++) {
for (let j = 0; j < 9; j++) {
if (j == 4) {//画楚河汉界
this.ctx.font = " bold 50px 楷书";
if (i == 1) {
this.ctx.fillText("楚 河", 500 + i * lattice, 30 + j * lattice + lattice / 2)
} else if (i == 6) {
this.ctx.fillText("汉 界", 500 + i * lattice, 30 + j * lattice + lattice / 2)
}
} else {
this.ctx.rect(500 + i * lattice, 20 + j * lattice, lattice, lattice);
}
// 画x
if ([3].includes(i) && [0, 7].includes(j)) {
this.ctx.moveTo(500 + i * lattice, 20 + j * lattice)
this.ctx.lineTo(500 + i * lattice + 200, 20 + j * lattice + 200)
this.ctx.moveTo(700 + i * lattice, 20 + j * lattice)
this.ctx.lineTo(500 + i * lattice, 20 + j * lattice + 200)
}
if ([2, 4, 6].includes(i) && [2, 5].includes(j)) {
this.drawTriangle(i, j)
}
if ([1, 7].includes(i) && [1, 6].includes(j)) {
this.drawTriangle(i, j)
}
if (i == 0 && [2, 5].includes(j)) {
let offset = 490;
this.ctx.moveTo(offset + 20 + i * lattice, 100 + j * lattice)
this.ctx.lineTo(offset + 20 + i * lattice, 110 + j * lattice)
this.ctx.lineTo(offset + 30 + i * lattice, 110 + j * lattice)
this.ctx.moveTo(offset + 30 + i * lattice, 130 + j * lattice)
this.ctx.lineTo(offset + 20 + i * lattice, 130 + j * lattice)
this.ctx.lineTo(offset + 20 + i * lattice, 140 + j * lattice)
}
if (i == 7 && [2, 5].includes(j)) {
let offset = 590;
this.ctx.moveTo(offset + i * lattice, 100 + j * lattice)
this.ctx.lineTo(offset + i * lattice, 110 + j * lattice)
this.ctx.lineTo(offset - 10 + i * lattice, 110 + j * lattice)
this.ctx.moveTo(offset - 10 + i * lattice, 130 + j * lattice)
this.ctx.lineTo(offset + i * lattice, 130 + j * lattice)
this.ctx.lineTo(offset + i * lattice, 140 + j * lattice)
}
}
}
this.ctx.closePath();
this.ctx.stroke();
}
// 画小三角
drawTriangle(i: number, j: number, offset: number = 490) {
if (i == 0 && [2, 5].includes(j)) {
let offset = 490;
this.ctx.moveTo(offset + 20 + i * lattice, 100 + j * lattice)
this.ctx.lineTo(offset + 20 + i * lattice, 110 + j * lattice)
this.ctx.lineTo(offset + 30 + i * lattice, 110 + j * lattice)
this.ctx.moveTo(offset + 30 + i * lattice, 130 + j * lattice)
this.ctx.lineTo(offset + 20 + i * lattice, 130 + j * lattice)
this.ctx.lineTo(offset + 20 + i * lattice, 140 + j * lattice)
} else if (i == 7 && [2, 5].includes(j)) {
let offset = 590;
this.ctx.moveTo(offset + i * lattice, 100 + j * lattice)
this.ctx.lineTo(offset + i * lattice, 110 + j * lattice)
this.ctx.lineTo(offset - 10 + i * lattice, 110 + j * lattice)
this.ctx.moveTo(offset - 10 + i * lattice, 130 + j * lattice)
this.ctx.lineTo(offset + i * lattice, 130 + j * lattice)
this.ctx.lineTo(offset + i * lattice, 140 + j * lattice)
} else {
this.ctx.moveTo(offset + i * lattice, 100 + j * lattice)
this.ctx.lineTo(offset + i * lattice, 110 + j * lattice)
this.ctx.lineTo(offset - 10 + i * lattice, 110 + j * lattice)
this.ctx.moveTo(offset + 20 + i * lattice, 100 + j * lattice)
this.ctx.lineTo(offset + 20 + i * lattice, 110 + j * lattice)
this.ctx.lineTo(offset + 30 + i * lattice, 110 + j * lattice)
this.ctx.moveTo(offset + 30 + i * lattice, 130 + j * lattice)
this.ctx.lineTo(offset + 20 + i * lattice, 130 + j * lattice)
this.ctx.lineTo(offset + 20 + i * lattice, 140 + j * lattice)
this.ctx.moveTo(offset - 10 + i * lattice, 130 + j * lattice)
this.ctx.lineTo(offset + i * lattice, 130 + j * lattice)
this.ctx.lineTo(offset + i * lattice, 140 + j * lattice)
}
}
// 绘制棋子
drawKiKos() {
for (let i = 0; i < this.initKios.length; i++) {
if (this.initKios[i] == "帅") {
this.redKiko.push(Kiko.getKiko(400, 920, ColorType.RED, this.kikoCanvasCtx, this.initKios[i], 38));
} else if (this.initKios[i] == "将") {
this.blackKiko.push(Kiko.getKiko(i * lattice, 20, ColorType.BLACK, this.kikoCanvasCtx, this.initKios[i], 38));
} else if (this.initKios[i] == "炮") {
this.blackKiko.push(Kiko.getKiko(100, 220, ColorType.BLACK, this.kikoCanvasCtx, this.initKios[i], 38));
this.blackKiko.push(Kiko.getKiko(700, 220, ColorType.BLACK, this.kikoCanvasCtx, this.initKios[i], 38));
this.redKiko.push(Kiko.getKiko(100, 720, ColorType.RED, this.kikoCanvasCtx, this.initKios[i], 38));
this.redKiko.push(Kiko.getKiko(700, 720, ColorType.RED, this.kikoCanvasCtx, this.initKios[i], 38));
} else if (this.initKios[i] == "卒") {
for (let v = 0; v < 5; v++) {
this.blackKiko.push(Kiko.getKiko(v * lattice * 2, 320, ColorType.BLACK, this.kikoCanvasCtx, this.initKios[i], 38));
}
} else if (this.initKios[i] == "兵") {
for (let v = 0; v < 5; v++) {
this.redKiko.push(Kiko.getKiko(v * lattice * 2, 620, ColorType.RED, this.kikoCanvasCtx, this.initKios[i], 38));
}
} else {
this.blackKiko.push(Kiko.getKiko(i * lattice, 20, ColorType.BLACK, this.kikoCanvasCtx, this.initKios[i], 38));
this.redKiko.push(Kiko.getKiko(i * lattice, 920, ColorType.RED, this.kikoCanvasCtx, this.initKios[i], 38));
}
}
}
// 获取选中棋子
getCheckKiko(x: number, y: number,) {
if (this.isStatus == ColorType.RED) {
return this.redKiko.find(item => {
if (item.x - item.size / 2 < x &&
item.x + item.size / 2 > x &&
item.y - item.size / 2 < y &&
item.y + item.size / 2 > y) {
return item;
}
})
}
return this.blackKiko.find(item => {
console.log(x, y)
if (item.x - item.size / 2 < x &&
item.x + item.size / 2 > x &&
item.y - item.size / 2 < y &&
item.y + item.size / 2 > y) {
return item;
}
})
}
}
enum ColorType {
BLACK = "black",
RED = "red",
}
// 棋子
abstract class Kiko {
color: ColorType;
x: number;
y: number;
size: number;
ctx: CanvasRenderingContext2D;
text: string;
static getKiko(x: number, y: number, color: ColorType, ctx: CanvasRenderingContext2D, text: string, size: number) {
switch (text) {
case "兵":
return new SoldierKiko(x, y, color, ctx, text, size);
case "卒":
return new SoldierKiko(x, y, color, ctx, text, size);
case "車":
return new SoldierKiko(x, y, color, ctx, text, size);
case "馬":
return new SoldierKiko(x, y, color, ctx, text, size);
case "象":
return new SoldierKiko(x, y, color, ctx, text, size);
case "士":
return new SoldierKiko(x, y, color, ctx, text, size);
case "将":
return new SoldierKiko(x, y, color, ctx, text, size);
case "帅":
return new SoldierKiko(x, y, color, ctx, text, size);
case "炮":
return new SoldierKiko(x, y, color, ctx, text, size);
default:
return new SoldierKiko(x, y, color, ctx, text, size);
}
}
static drawKiko(arr:Kiko[]){
arr.forEach(item=>item.draw());
}
constructor(x: number, y: number, color: ColorType, ctx: CanvasRenderingContext2D, text: string, size: number) {
this.x = x;
this.y = y;
this.color = color;
this.size = size;
this.ctx = ctx;
this.text = text;
this.draw();
}
draw() {
this.ctx.strokeStyle = this.color
this.ctx.beginPath();
this.ctx.lineWidth = 1
this.ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
this.ctx.fillStyle = "white";
this.ctx.fill();
this.ctx.stroke();
this.ctx.beginPath();
this.ctx.lineWidth = 2
this.ctx.fillStyle = this.color;
this.ctx.arc(this.x, this.y, this.size - 5, 0, Math.PI * 2);
this.ctx.font = `bold ${this.size + 8}px 楷书`;
this.ctx.fillText(this.text, this.x - this.size / 2 - 3, this.y + this.size / 2 - 2)
this.ctx.stroke();
this.ctx.closePath();
}
abstract move(x:number,y:number): void;
}
// 兵
class SoldierKiko extends Kiko {
constructor(x: number, y: number, color: ColorType, ctx: CanvasRenderingContext2D, text: string, size: number) {
super(x, y, color, ctx, text, size);
}
move(x:number,y:number): void {
console.log(y,this.y)
if(this.y>y){
this.y-=100;
}else {
if(this.y>320)return;
this.y+=100;
}
// 移动
this.ctx.clearRect(-50,-50,map.width+100,map.height+100)
}
}
export default Chess