前几天学了微软开发的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: 用于对棋盘和棋子加载并实现下棋逻辑的类;
======================================================================================================
最后,我还想说两句,但不知道该说什么,那就算了。