使用typescript和egret wing3开发简单的单机五子棋游戏

前几天学了微软开发的Typescript,这种语言是用面向对象的思想来写,运行的时候会编译为js,可以使用tsc编译为js代码,既然学了就用一下,配合egret引擎及egret wing3做一个十分基本的小游戏练下手,给一些更新的新手参考一下,有错误和建议可以提出来,谢谢。

服务器框架用的是pemelo。


  • 基本的链接:
    • Node.js:https://nodejs.org/en/ 。
    • TS API:https://www.tslang.cn/ 。
    • egret引擎及egret wing3下载页面:https://www.egret.com/index 。
    • egret API:http://developer.egret.com/cn/apidoc/ 。

看到这说明你已经了解ts了,那么基本的语法就不用说了,你看你长得那么聪明,下面开始介绍项目。


最主要是五子棋判断的方法,其他的东西是给没用过的提供的

1、使用egret wing3新建一个egret游戏项目,项目名暂且叫GoBang,项目简单,里面很多文件不用去看,只要记住根目录下的index.html是主页面,其中:

 - data-entry-class="Main" 设置项目的入口文件,表示项目的入口类,默认为Main,如果需要自定义的话需要在项目中先创建类,然后在这里配置类的名字。
 - data-orientation="auto" 设置旋转模式。
 - data-scale-mode="showAll" 设置缩放模式。
 - data-frame-rate="60" 这里是运行的帧率。
 - data-content-width="480" 和 data-content-height="800" 用来设置舞台的设计宽和高
 - data-show-paint-rect="false" 设置显示脏矩形的重绘区域。
 - data-multi-fingered="1" 设置多指触摸
 - data-show-fps="false" data-show-log="false" 这里设置显示帧率和log,只有在调试时会显示,发布的版本会去掉。
 - data-log-filter=" " 设置一个正则表达式过滤条件,日志文本匹配这个正则表达式的时候才显示这条日志。如 data-log-filter="^egret" 表示仅显示以 egret 开头的日志。
 - data-show-fps-style="x:0,y:0,size:30,textColor:0x00c200,bgAlpha:0.9" 这里设置fps面板的样式。目前支持默认的这几种设置,修改其值即可,比如修改面板位置可以设置x和y,改变大小可以设置size,改变文字颜色textColor,改变背景面板的透明度bgAlpha。

2、

  • 在src源文件目录下建一个文件夹,里面新建3个文件:DrawChessBs.ts,DrawChessMen.ts,GoBangPlaying.ts,分别表示画棋盘的类,画棋子的类,用于对棋盘和棋子加载并实现下棋逻辑的类。
  • src目录下有两个文件:LoadingUI.ts和Main.ts,前一个看名字就知道,这里先不用管,后面的名字正是
    index.html的data-entry-class设置的入口类,可以随意改变,这里默认Main。
  • 其余json什么的加载和配置文件本项目用不着关心,想看也可以。

3、下面放上代码以供参考

注:
	设计长宽为800*800,所以修改"data-content-width"和"data-content-height"均修改为800,再次刷新页面,否则页面会加载不全

  • index.html:

<!--index.html-->
<!DOCTYPE HTML>
<html>
<head>
    <meta charset="utf-8">
    <title>Egret</title>
    <meta name="viewport" content="width=device-width,initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no" />
    <meta name="apple-mobile-web-app-capable" content="yes" />
    <meta name="full-screen" content="true" />
    <meta name="screen-orientation" content="portrait" />
    <meta name="x5-fullscreen" content="true" />
    <meta name="360-fullscreen" content="true" />
    <style>
        html, body {
            -ms-touch-action: none;
            background: #888888;
            padding: 0;
            border: 0;
            margin: 0;
            height: 100%;
        }
    </style>
</head>

<!--看似很多,但大部都是默认的,本项目只要注意"data-content-width",和"data-content-height",均改为800即可-->
<!-- 有些东西我加点注释 -->
<body>
    <div style="margin: auto;width: 100%;height: 100%;" class="egret-player"
         data-entry-class="Main"
         data-orientation="auto"
         data-scale-mode="showAll"								
         data-frame-rate="30"									<!-- 帧频数-->
         data-content-width="800"								<!-- 游戏宽-->
         data-content-height="800"								<!-- 高-->
         data-show-paint-rect="false"
         data-multi-fingered="2"								<!-- 多指-->
         data-show-fps="false" 									<!-- 这个是显示性能的,fps-->
         data-show-log="false"									<!-- 这个是显示在左上角一些信息-->
         data-show-fps-style="x:0,y:0,size:12,textColor:0xffffff,bgAlpha:0.9">
    </div>
<script>

	//引入js文件,如果游戏ts文件非常多,会将ts转为js,然后放在manifest.json内,通过下面的GET方式引入
    var loadScript = function (list, callback) {
        var loaded = 0;
        var loadNext = function () {
            loadSingleScript(list[loaded], function () {
                loaded++;
                if (loaded >= list.length) {
                    callback();
                }
                else {
                    loadNext();
                }
            })
        };
        loadNext();
    };

    var loadSingleScript = function (src, callback) {
        var s = document.createElement('script');
        s.async = false;
        s.src = src;
        s.addEventListener('load', function () {
            s.parentNode.removeChild(s);
            s.removeEventListener('load', arguments.callee, false);
            callback();
        }, false);
        document.body.appendChild(s);
    };

    var xhr = new XMLHttpRequest();
    xhr.open('GET', './manifest.json?v=' + Math.random(), true);
    xhr.addEventListener("load", function () {
        var manifest = JSON.parse(xhr.response);
        var list = manifest.initial.concat(manifest.game);
        loadScript(list, function () {
            /**
             * {
             * "renderMode":, //引擎渲染模式,"canvas" 或者 "webgl"
             * "audioType": 0 //使用的音频类型,0:默认,2:web audio,3:audio
             * "antialias": //WebGL模式下是否开启抗锯齿,true:开启,false:关闭,默认为false
             * "retina": //是否基于devicePixelRatio缩放画布
             * }
             **/
            egret.runEgret({ renderMode: "webgl", audioType: 0 });
        });
    });
    xhr.send(null);
</script>
</body>

</html>



  • Main.ts
/**
 * 
 * author:Sclifftop
 * date:17.08.01
 * project:GoBang
 * FileName:Main.ts
 * 
 */



    //Main.ts上面是新建文件时自动生成的,有加载图片资源,现在没用到这么多不用管,只要拉到最后修改一下createGameScenee()即可,如下:
    
    /**
     * 创建游戏场景
     * Create a game scene
     */
    private createGameScene() {

       //棋盘的所有操作
       let gbp:GoBangPlaying=new GoBangPlaying();
       this.addChild(gbp);
        
    }



  • DrawChessBs.ts

/**
 * 
 * author:Sclifftop
 * date:17.08.01
 * project:GoBang
 * FileName:DrawChessBs.ts
 * 
 */

class DrawChessBs extends egret.DisplayObjectContainer {

	//棋盘长和宽
	private CLENGTH: number = 785;
	//棋盘左上角开始的位置
	private BEGINPOSITION: number = 15;
	//每个棋盘格的长度
	private RECTLENGTH: number = 35;
	//每个点开始的格位置
	private POINTBEGINPN: number = 3;
	//点增量
	private POINTSTEP: number = 8;
	public constructor() {
		super();
		this.addEventListener(egret.Event.ADDED_TO_STAGE, this.setBg, this);
		this.addEventListener(egret.Event.ADDED_TO_STAGE, this.drawLine, this);
		this.addEventListener(egret.Event.ADDED_TO_STAGE, this.drawFourLc, this);
	}

	private setBg() {
		//设置背景
		var bg: egret.Shape = new egret.Shape();
		bg.graphics.beginFill(0xDDDDDD);
		bg.graphics.drawRect(0, 0, this.stage.stageWidth, this.stage.stageHeight);
		bg.graphics.endFill();
		//添加至页面
		this.addChild(bg);
	}
	//画棋盘线
	private drawLine(event: egret.Event) {
		let bg: egret.Shape = new egret.Shape();
		bg.graphics.lineStyle(2, 0x999999);
		for (let i = 0; i < Math.ceil(this.CLENGTH / this.RECTLENGTH); i++) {
			bg.graphics.moveTo(this.BEGINPOSITION + i * this.RECTLENGTH, this.BEGINPOSITION);
			bg.graphics.lineTo(this.BEGINPOSITION + i * this.RECTLENGTH, this.CLENGTH);
			bg.graphics.moveTo(this.BEGINPOSITION, this.BEGINPOSITION + i * this.RECTLENGTH);
			bg.graphics.lineTo(this.CLENGTH, this.BEGINPOSITION + i * this.RECTLENGTH);
		}
		bg.graphics.endFill();
		this.addChild(bg);
	}
	//画五个点,用于确定位置
	private drawFourLc(event: egret.Event) {
		let flO: egret.Shape = new egret.Shape();
		let flT: egret.Shape = new egret.Shape();
		for (let i = this.POINTBEGINPN; i < Math.ceil(this.CLENGTH / this.RECTLENGTH); i += this.POINTSTEP) {
			flO.graphics.beginFill(0x888888, 1);
			flO.graphics.drawCircle(this.BEGINPOSITION + i * this.RECTLENGTH, this.BEGINPOSITION + i * this.RECTLENGTH, 4);
			flT.graphics.beginFill(0x888888, 1);
			flT.graphics.drawCircle(this.BEGINPOSITION + i * this.RECTLENGTH, this.CLENGTH - i * this.RECTLENGTH, 4);
		}
		flO.graphics.endFill();
		flT.graphics.endFill();
		this.addChild(flO);
		this.addChild(flT);
	}
}





  • DrawChessMen.ts


/**
 * 
 * author:Sclifftop
 * date:17.08.01
 * project:GoBang
 * FileName:DrawChessMen.ts
 * 
 */

class DrawChessMen extends egret.DisplayObjectContainer {

	//棋子颜色
	private CHESSMENCOLOR: number = 0;
	//棋子半径
	private CHESSMENRADIUS: number = 15;
	//棋子透明度
	private CHESSALP: number = 0.2;
	public constructor() {
		super();
	}
	public drawChessMen(x: number, y: number, k: number) {
		let chess: egret.Shape = new egret.Shape();
		//0黑棋1白棋
		if (k == 1) {
			this.CHESSMENCOLOR = 0xffffff;
		} else if (k == 0) {
			this.CHESSMENCOLOR = 0x000000;
		}
		for (let i = 0; i < this.CHESSMENRADIUS; i++) {
			chess.graphics.beginFill(this.CHESSMENCOLOR, this.CHESSALP);
			chess.graphics.drawCircle(x, y, i + 1);
		}
		chess.graphics.endFill();
		this.addChild(chess);
	}

}



  • GoBangPlaying.ts

/**
 * 
 * author:Sclifftop
 * date:17.8.1
 * project:GoBang
 * FileName:GoBangPlaying.ts
 * 
 */


class GoBangPlaying extends egret.DisplayObjectContainer {

	//左上角开始位置
	private STARTPOSITION: number = 15;
	private ENDPOSITION: number = 785;
	//每个棋盘格的长度
	private RECTLENGTH: number = 35;
	//表示棋子的编号:1是白,0是黑,0先手
	private CHESSMENINDEX: number = 0;
	//表示点击的次数
	private CLICKNUM: number = 1;
	//新建数组,用于存储棋子的位置
	private arr: number[][] = new Array();
	//标志棋子的输赢
	private flag: number = 0;
	private chessMenString: string = "";
	private dcm: DrawChessMen = new DrawChessMen();
	public constructor() {
		super();
		//初始化二维数组
		this.iniArray();
		//画棋盘
		let db: DrawChessBs = new DrawChessBs();
		this.addChild(db);

		this.touchEnabled = true;
		this.addEventListener(egret.TouchEvent.TOUCH_TAP, this.selectChessMen, this);
	}

	//根据点击判断选择棋盘位置并下对应的棋
	private selectChessMen(evt: egret.TouchEvent) {

		let clickX = evt.stageX;
		let clickY = evt.stageY;

		//点击的位置不能小于&&不能大于,否则无效
		if ((clickX >= (this.STARTPOSITION - 8) && clickY >= (this.STARTPOSITION - 8)) && (clickX <= (this.ENDPOSITION + 4) && clickY <= (this.ENDPOSITION + 4))) {

			console.log(this.getPosition(clickX), this.getPosition(clickY));
			//若该位没有棋子,可以放置
			if (this.arr[this.getPosition(clickX)][this.getPosition(clickY)] == 2) {
				this.dcm.drawChessMen(this.getInt(clickX), this.getInt(clickY), this.CHESSMENINDEX, );
				//棋子放下后,则改变标志位
				if (this.CHESSMENINDEX == 1)
					this.arr[this.getPosition(clickX)][this.getPosition(clickY)] = 1;
				else
					this.arr[this.getPosition(clickX)][this.getPosition(clickY)] = 0;
				this.judgeAndResult(this.getPosition(clickX), this.getPosition(clickY), this.CHESSMENINDEX);
				console.log("-----------已下了" + this.CLICKNUM + "颗棋子------------");
				//自增
				this.CLICKNUM++;

			}
			// console.log("arr"+this.arr[this.getPosition(clickX)][this.getPosition(clickY)]);
			if (this.CLICKNUM % 2 == 0) {
				this.CHESSMENINDEX = 1;
			} else {
				this.CHESSMENINDEX = 0;
			}
			this.addChild(this.dcm);
		} else {
			window.alert("您好,不能在此位置放置棋子");
		}

	}

	//用于计算所在的格子位数
	private getPosition(d: number) {
		return Math.round((d - this.STARTPOSITION) / this.RECTLENGTH) + 1;
	}
	//封装为方法,用于计算出点击的位置
	private getInt(t: number) {
		return this.STARTPOSITION + Math.round((t - this.STARTPOSITION) / this.RECTLENGTH) * 35;
	}


	//判断棋子情况
	private judgeAndResult(x: number, y: number, chessIndex: number) {

		//水平方向
		let horizontalDirection: number = 0;
		//垂直方向
		let verticalDirection: number = 0;
		//左上<=>右下
		let leftObliqueDirection: number = 0;
		//右上<=>左下
		let rightObliqueDirection: number = 0;
		for (let i = x; i >= 0; i--) {
			if (this.arr[i][y] != chessIndex) {
				break;
			}
			horizontalDirection++;
		}
		for (let i = x + 1; i < 23; i++) {
			if (this.arr[i][y] != chessIndex) {
				break;
			}
			horizontalDirection++;
		}
		for (let i = y; i >= 0; i--) {
			if (this.arr[x][i] != chessIndex) {
				break;
			}
			verticalDirection++;
		}
		for (let i = y + 1; i < 23; i++) {
			if (this.arr[x][i] != chessIndex) {
				break;
			}
			verticalDirection++;
		}
		for (let i = x, j = y; i >= 0 && j >= 0; i-- , j--) {
			if (i < 0 || j < 0 || this.arr[i][j] != chessIndex) {
				break;
			}
			leftObliqueDirection++;
		}

		for (let i = x + 1, j = y + 1; i < 23 && j < 23; i++ , j++) {
			if (i >= 23 || j >= 23 || this.arr[i][j] != chessIndex) {
				break;
			}
			leftObliqueDirection++;
		}

		for (let i = x, j = y; i >= 0 && j < 23; i-- , j++) {
			if (i < 0 || j >= 15 || this.arr[i][j] != chessIndex) {
				break;
			}
			rightObliqueDirection++;
		}
		for (var i = x + 1, j = y - 1; i < 23 && j >= 0; i++ , j--) {
			if (i >= 23 || j < 0 || this.arr[i][j] != chessIndex) {
				break;
			}
			rightObliqueDirection++;
		}
		if (horizontalDirection >= 5 || verticalDirection >= 5 || leftObliqueDirection >= 5 || rightObliqueDirection >= 5) {
			if (chessIndex == 0) {
				this.flag = 21;
			} else if (chessIndex == 1) {
				this.flag = 20;
			}
			if (this.flag == 20) {
				this.chessMenString = "白";
				this.iniParam(this.flag, this.chessMenString);
			} else if (this.flag == 21) {
				this.chessMenString = "黑"
				this.iniParam(this.flag, this.chessMenString);
			}
		}
	}


	//初始化数组
	private iniArray() {
	
		// let tempArr = [];
		// for (let i = 0; i < 29; i++) {
		// 	tempArr.push(2);
		// }
		// for (let j = 0; j < 30; j++) {
		// 	this.arr.push(tempArr);
		// }
		
		//可以改成上面注释的,数据少效率乎一样,我闲,所以写这么多2,也可以使用一个临时的 tempArr2,然后 this.arr=tempArr2
		for (let j = 0; j < 30; j++) {
			this.arr.push([2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]);
		}
	}

	//输出信息,并重新开始一局
	private iniParam(f: number, chessMenS: string) {
		window.alert(chessMenS + "子胜利,请点击'确定'按钮以重新开始一局");
		this.flag = 0;
		this.iniArray();
		//清除所有棋子,重新开始
		// 可以使用chess.graphics.clear();来清除所有棋子
		//没有使用清除,更简单地刷新当前页面
		window.location.reload();
	}
}

4、截图:



  • 基本的棋盘界面:

基本棋盘


  • 下棋界面:

这里写图片描述



  • 赢棋界面:和上面一样,就是多个提示框,略。

5、项目很简单,主要是那个判断下棋的逻辑,其他没什么,没做计时(计时很简单,获取本地时间判断就好,或者用egret.getTimer() )、默认黑子先手、没有做与电脑对奕(如果你愿意可以自己写一个,自己下完之后,在最佳的位置下对方的棋子)、画的界面,按钮你可以自己加个重开的,不过架个服务器,可以和另一个人玩。


附:
======================================================================================================
项目:		  GoBang;
项目描述:	五子棋;
游戏方法:	黑棋先手,若任意方向棋子率先连成五个以上则赢得本局,若一方赢得本局,则重开,进行新一轮的游戏;

======================================================================================================

硬件: 		pc;
OS:   		 win 7 64位;
浏览器:		推荐Chrome内核;因为有控制台输出信息;

======================================================================================================

index.html:		    主页面;
Main.ts:		    主类,用于实现对资源加载和游戏场景的创建;
DrawChessBs.ts:		用于画棋盘的类;
DrawChessMen.ts:	用于画棋子的类;
GoBangPlaying.ts:	用于对棋盘和棋子加载并实现下棋逻辑的类;

======================================================================================================

最后,我还想说两句,但不知道该说什么,那就算了。


  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值