【JavaScript游戏开发】使用HTML5 canvas开发的网页版中国象棋项目

//V1.0 : 实现棋子的布局,画布及游戏场景的初始化
//V2.0 : 实现棋子的颜色改变
//V3.0 :实现所有象棋的走棋规则
//V4.0 : 实现所有棋子的吃子功能

完整的项目源码已经开源:https://github.com/xiugangzhang/ChineseChess

项目在线预览地址:

http://htmlpreview.github.io/?https://github.com/xiugangzhang/ChineseChess/blob/master/ChineseChess.html

目前就实现了上面的几个功能,最近也么时间再弄了,需要的朋友可以自己下载下来继续开发哈!

主要特点:

1.无任何插件和第三方库,纯原生js实现

2.没使用任何素材,棋盘和棋子都是由canvas画布绘制

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
    </style>
</head>

<body>
<canvas id="myCanvas" width="600px" height="660px">
</canvas>
<script>


    //V1.0 : 实现棋子的布局,画布及游戏场景的初始化
    //V2.0 : 实现棋子的颜色改变
    //V3.0 :实现所有象棋的走棋规则
    //V4.0 : 实现所有棋子的吃子功能
    var canvas = document.getElementById("myCanvas");
    var context = canvas.getContext("2d");

    /**
     * 棋子对象
     * @param x
     * @param y
     * @param color
     * @constructor
     */
    function Chess(x, y, color, type) {
        this.x = x;
        this.y = y;
        this.color = color;


        this.type = type;

        // 记录颜色
        this.chessColor = color;

        // 是否死掉
        this.isDead = false;
    }

    // 成员函数
    Chess.prototype = {
        _getChessText: function () {
            switch (this.type) {
                case "CHE":
                    return "车";
                case "MA":
                    return "马";
                case "PAO":
                    return "炮";
                case "BING":
                    return "兵";
                case "JIANG":
                    return "将";
                case "SHI":
                    return "士";
                case "XIANG":
                    return "相";
            }
            return "错误";
        }
    }

    /**
     * 游戏场景
     * @constructor
     */
    function Game() {

        // 存放当前棋盘上所有的棋子
        this._chesses = [];

        //初始位置
        this._initX = 60;
        this._initY = 60;

        // 判断鼠标是否点击有棋子
        this._selectedChess = null;

        this._initCount = 0;
    }

    Game.prototype = {
        // 场景的初始化
        execute: function () {
            this._initChesses();
            this._start();
        },
        _initChesses: function () {
            // 绘制棋子(初始位置)
            // 总共需要绘制32颗棋子

            // 红色棋子
            var redChess;
            for (var i = 0; i < 4; i++) {
                for (var j = 0; j < 9; j++) {
                    if ((i == 0 && j == 0) || (j == 8 && i == 0)) {
                        // 把棋子的颜色传进去
                        redChess = new Chess(j, i, "red", "CHE");
                        this._chesses.push(redChess);
                    } else if ((j == 1 && i == 0) || (j == 7 && i == 0 )) {
                        redChess = new Chess(j, i, "red", "MA");
                        this._chesses.push(redChess);
                    } else if ((j == 2 && i == 0) || (j == 6 && i == 0)) {
                        redChess = new Chess(j, i, "red", "XIANG");
                        this._chesses.push(redChess);
                    } else if ((j == 3 && i == 0) || (j == 5 && i == 0)) {
                        redChess = new Chess(j, i, "red", "SHI");
                        this._chesses.push(redChess);
                    } else if ((j == 4 && i == 0)) {
                        redChess = new Chess(j, i, "red", "JIANG");
                        this._chesses.push(redChess);
                    } else if ((j == 1 && i == 2) || (j == 7 && i == 2)) {
                        redChess = new Chess(j, i, "red", "PAO");
                        this._chesses.push(redChess);
                    } else if ((j == 0 && i == 3) || (j == 2 && i == 3) || (j == 4 && i == 3) || (j == 6 && i == 3) || (j == 8 && i == 3)) {
                        redChess = new Chess(j, i, "red", "BING");
                        this._chesses.push(redChess);
                    }


                }
            }

            // 绘制黑色棋子
            var blackChess;
            for (var i = 6; i < 10; i++) {
                for (var j = 0; j < 10; j++) {
                    if ((j == 0 && i == 9) || (j == 8 && i == 9)) {
                        blackChess = new Chess(j, i, "black", "CHE");
                        this._chesses.push(blackChess);
                    } else if ((j == 1 && i == 9) || (j == 7 && i == 9)) {
                        blackChess = new Chess(j, i, "black", "MA");
                        this._chesses.push(blackChess);
                    } else if ((j == 2 && i == 9) || (j == 6 && i == 9)) {
                        blackChess = new Chess(j, i, "black", "XIANG");
                        this._chesses.push(blackChess);
                    } else if ((j == 3 && i == 9) || (j == 5 && i == 9)) {
                        blackChess = new Chess(j, i, "black", "SHI");
                        this._chesses.push(blackChess);
                    } else if (j == 4 && i == 9) {
                        blackChess = new Chess(j, i, "black", "JIANG");
                        this._chesses.push(blackChess);
                    } else if ((j == 1 && i == 7) || (j == 7 && i == 7)) {
                        blackChess = new Chess(j, i, "black", "PAO");
                        this._chesses.push(blackChess);
                    } else if ((j == 0 && i == 6) || (j == 2 && i == 6) || (j == 4 && i == 6) || (j == 6 && i == 6) || (j == 8 && (i == 6))) {
                        blackChess = new Chess(j, i, "black", "BING");
                        this._chesses.push(blackChess);
                    }
                }
            }

            //console.log(redChess);
            //console.log(blackChess);
            console.log(this._chesses);

        },
        /**
         * 绘制棋子 车马相士将
         * @private
         */
        _drawChesses: function () {


            var isDeadChess = null;
            // 根据游戏中棋子的数目来绘制棋子
            // 游戏中的棋子始终是32颗, 因此只能根据棋子是否存活来决定是否绘制这个棋子(原来的位置还是有棋子, 这是让他隐藏起来)
            for (var i = 0; i < this._chesses.length; i++) {
                var chess = this._chesses[i];

                // 原来的位置还是有棋子, 这是让他隐藏起来
                if (!chess.isDead) {
                    // 只有当这个棋子的属性isDead = false; 才绘制这个棋子
                    // 根据棋子的属性来绘制
                    context.fillStyle = "#C78843";
                    context.beginPath();
                    // 绘制棋子(注意要把棋子的初始位置复位)
                    context.arc(chess.x * 60 + this._initX, chess.y * 60 + this._initY, 25, 0, Math.PI * 2, true);
                    context.closePath();
                    context.fill();


                    // 绘制文本
                    if (chess.color == "red") {
                        context.fillStyle = 'red';
                    }
                    if (chess.color == "black") {
                        context.fillStyle = 'black';
                    }
                    if (chess.color == "blue") {
                        context.fillStyle = 'blue';
                    }

                    context.font = '43px 华文新魏';
                    context.fillText(chess._getChessText(), chess.x * 60 + this._initX - 22, chess.y * 60 + this._initY + 10);
                }
                else {


                    isDeadChess = chess;

                }


            }

            // 有棋子被吃了,就重新开始
            //this._selectedChess = null;
            if (this._initCount == 0) {

                //console.log(chess.x+","+chess.y+","+chess.type+"已经隐藏");
            }


        },
        _drawChessboard: function () {

            context.strokeStyle = "black";
            // 绘制棋盘外边界
            context.lineWidth = 3;
            context.beginPath();
            context.moveTo(0, 0);
            context.lineTo(600, 0);
            context.closePath();
            context.stroke();

            context.beginPath();
            context.moveTo(0, 0);
            context.lineTo(0, 660);
            context.closePath();
            context.stroke();

            context.beginPath();
            context.moveTo(600, 0);
            context.lineTo(600, 660);
            context.closePath();
            context.stroke();

            context.beginPath();
            context.moveTo(0, 660);
            context.lineTo(660, 660);
            context.closePath();
            context.stroke();

            // 内部的外边界
            context.beginPath();
            context.moveTo(40, 40);
            context.lineTo(40, 620);
            context.closePath();
            context.stroke();

            context.beginPath();
            context.moveTo(40, 40);
            context.lineTo(560, 40);
            context.closePath();
            context.stroke();

            context.beginPath();
            context.moveTo(560, 40);
            context.lineTo(560, 620);
            context.closePath();
            context.stroke();

            context.beginPath();
            context.moveTo(560, 620);
            context.lineTo(40, 620);
            context.closePath();
            context.stroke();


            //棋盘横线
            context.lineWidth = 1;
            for (var i = 1; i < 11; i++) {
                context.beginPath();
                context.moveTo(60, 60 * i);
                context.lineTo(540, 60 * i);
                context.closePath();
                context.stroke();
            }

            // 棋盘纵线
            for (var i = 1; i < 10; i++) {
                context.beginPath();
                context.moveTo(i * 60, 60);
                context.lineTo(i * 60, 300);
                context.closePath();
                context.stroke();
            }

            for (var i = 1; i < 10; i++) {
                context.beginPath();
                context.moveTo(i * 60, 360);
                context.lineTo(i * 60, 600);
                context.closePath();
                context.stroke();
            }

            context.beginPath();
            context.moveTo(60, 300);
            context.lineTo(60, 360);
            context.closePath();
            context.stroke();

            context.beginPath();
            context.moveTo(540, 300);
            context.lineTo(540, 360);
            context.closePath();
            context.stroke();


            // 棋盘斜线
            context.beginPath();
            context.moveTo(240, 60);
            context.lineTo(360, 180);
            context.closePath();
            context.stroke();

            context.beginPath();
            context.moveTo(360, 60);
            context.lineTo(240, 180);
            context.closePath();
            context.stroke();

            context.beginPath();
            context.moveTo(240, 480);
            context.lineTo(360, 600);
            context.closePath();
            context.stroke();

            context.beginPath();
            context.moveTo(360, 480);
            context.lineTo(240, 600);
            context.closePath();
            context.stroke();

            // 绘制炮的位置(左上)
            context.beginPath();
            context.moveTo(115, 160);
            context.lineTo(115, 175);
            context.closePath();
            context.stroke();

            context.beginPath();
            context.moveTo(115, 175);
            context.lineTo(100, 175);
            context.closePath();
            context.stroke();

            context.beginPath();
            context.moveTo(125, 160);
            context.lineTo(125, 175);
            context.closePath();
            context.stroke();

            context.beginPath();
            context.moveTo(125, 175);
            context.lineTo(140, 175);
            context.closePath();
            context.stroke();

            context.beginPath();
            context.moveTo(115, 185);
            context.lineTo(115, 200);
            context.closePath();
            context.stroke();

            context.beginPath();
            context.moveTo(115, 185);
            context.lineTo(100, 185);
            context.closePath();
            context.stroke();

            context.beginPath();
            context.moveTo(125, 185);
            context.lineTo(125, 200);
            context.closePath();
            context.stroke();

            context.beginPath();
            context.moveTo(125, 185);
            context.lineTo(140, 185);
            context.closePath();
            context.stroke();


            // 右上
            context.beginPath();
            context.moveTo(475, 175);
            context.lineTo(460, 175);
            context.closePath();
            context.stroke();

            context.beginPath();
            context.moveTo(475, 175);
            context.lineTo(475, 160);
            context.closePath();
            context.stroke();

            context.beginPath();
            context.moveTo(485, 160);
            context.lineTo(485, 175);
            context.closePath();
            context.stroke();

            context.beginPath();
            context.moveTo(485, 175);
            context.lineTo(500, 175);
            context.closePath();
            context.stroke();

            context.beginPath();
            context.moveTo(485, 185);
            context.lineTo(485, 200);
            context.closePath();
            context.stroke();

            context.beginPath();
            context.moveTo(485, 185);
            context.lineTo(500, 185);
            context.closePath();
            context.stroke();

            context.beginPath();
            context.moveTo(475, 185);
            context.lineTo(475, 200);
            context.closePath();
            context.stroke();

            context.beginPath();
            context.moveTo(475, 185);
            context.lineTo(460, 185);
            context.closePath();
            context.stroke();

            // 左下
            context.beginPath();
            context.moveTo(115, 485);
            context.lineTo(115, 500);
            context.closePath();
            context.stroke();

            context.beginPath();
            context.moveTo(115, 485);
            context.lineTo(100, 485);
            context.closePath();
            context.stroke();


            context.beginPath();
            context.moveTo(115, 475);
            context.lineTo(100, 475);
            context.closePath();
            context.stroke();

            context.beginPath();
            context.moveTo(115, 475);
            context.lineTo(115, 460);
            context.closePath();
          
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值