代码改变世界

JS开发HTML5游戏《悠悠考拉》(三)

2016-04-19 17:25  一切皆修行  阅读(4304)  评论(15编辑  收藏  举报

                                        (点击图片可进入试玩)

本篇文章为第三部分内容,这篇文章将接着上篇文章的内容,这篇文章的主要内容有:

7、游戏中的暂停与结束处理

8、排行榜界面

 

七、游戏中的暂停与结束处理

7.1 暂停

暂停处理:在游戏中,秋千的摇摆、柱子的移动等都是通过Tween动画实现的,例如秋千摇摆我们可以加TweenRation动画、柱子移动可以加TweenPosition动画。当我们按下暂停键时,此时,秋千与柱子还有考拉等应该是静止的,我还希望能弹出另一个界面,该界面有一些界面按钮,点击按钮可以实现对应的操作,关闭弹出的界面时,我们又可以继续游戏。首先我们可以在Main.js中加入代码对暂停按钮进行监听点击事件:代码如下,

 1 var Main = qc.defineBehaviour('qc.Koala.ui.Main', qc.Behaviour, function() {
 2     // 风值
 3     this.windValue = 0;
 4 
 5     // 掉落事件控制器
 6     this.dropTimer = null;
 7 
 8     // 跳台对象
 9     this._step = null;
10 
11     // 秋千对象
12     this.swing = null;
13 }, {
14     // 柱子池
15     pillarPool : qc.Serializer.NODE,
16     // 考拉节点
17     koala : qc.Serializer.NODE,
18     // 暂停按钮
19     pauseBtn : qc.Serializer.NODE,
20     // 风值
21     wind : qc.Serializer.NODE,
22     // 风向
23     windDirection : qc.Serializer.NODE,
24     // 分数节点
25     score : qc.Serializer.NODE
26 });
27 /**
28  * 初始化
29  */
30 Main.prototype.awake = function() {
31     var self = this;
32 
33     // 监听暂停按钮点击事件
34     this.addListener(this.pauseBtn.onClick, this._pause, this);
35 
36     // 继续游戏时,恢复暂停按钮交互
37     this.addListener(qc.Koala.onContinue, function() {
38         this.pauseBtn.interactive = true;
39     }, this);
40 };
41 /**
42  * 暂停游戏
43  */
44 Main.prototype._pause = function () {
45     // 如果游戏结束,则暂停按钮点击不做任何处理
46     if (qc.Koala.logic.me.isDie)
47         return;
48 
49     // 设置游戏暂停状态
50     qc.Koala.logic.me.paused = true;
51 
52     // 派发游戏暂停事件
53     qc.Koala.onPause.dispatch();
54 };
View Code

在该代码中有qc.Koala.onPause.dispatch(),意思是派发暂停事件。而我们可以在在Scripts/ui/Koala.js中加入事件接收,并停止秋千与考拉的动作从而达到暂停效果。代码如下所示:

 1 var Koala = qc.defineBehaviour('qc.Koala.ui.Koala', qc.Behaviour, function() {
 2     // 秋千对象
 3     this.swingScript = null;
 4 
 5     // 考拉当前播放的动作
 6     this.currAnimation = 'stand';
 7 }, {
 8     // 相机节点
 9     camera : qc.Serializer.NODE,
10     // 特效节点
11     effect : qc.Serializer.NODE,
12     // 文本
13     labelImg : qc.Serializer.NODE,
14     // 分数
15     scoreImg : qc.Serializer.NODE,
16     // 死亡效果图片
17     dieImg : qc.Serializer.NODE,
18     // 刹车效果图片
19     brakeImg : qc.Serializer.NODE
20 });
21 
22 /**
23  * 初始化
24  */
25 Koala.prototype.awake = function () {
26     // 监听游戏暂停事件
27     this.addListener(qc.Koala.onPause, this._pause, this);
28 
29 };
30 
31 /**
32  * 暂停游戏
33  */
34 Koala.prototype._pause = function () {
35     this.swingScript.stop();
36     this.gameObject.stop();
37 
38     this.labelImg.getScript('qc.TweenAlpha').onFinished.removeAll(this);
39 
40     // 并移除动作结束监听
41     var s = this.gameObject.getScript('qc.TweenPosition');
42     s.onFinished.remove(this.take, this);
43 
44     // 停止考拉走路位移动画
45     qc.Tween.stopGroup(this.gameObject, 3);
46 };
View Code

此时,我还希望在暂停的同时能够弹出一个菜单界面。弹出的菜单界面效果图如下所示:

菜单界面具体布局我就不详述了,可以参看前两篇文章的界面布局,也可以查看更详细的界面布局信息《界面布局》。前面我们讲过,当按下暂停按钮时,该菜单界面也会弹出来。我们可以创建一个脚本:Pause.js,该脚本的主要功能是接收游戏暂停事件的派送、点击"关闭"按钮时又继续游戏、以及上述中的按钮按下时对应的功能,排行榜与分享的具体实现我会在后续游戏结束处理中详细讲述。代码如下:

 1 var Pause = qc.defineBehaviour('qc.Koala.ui.Pause', qc.Behaviour, function() {
 2 }, {
 3     // 继续游戏按钮
 4     continueBtn : qc.Serializer.NODE,
 5     restartBtn : qc.Serializer.NODE,
 6     shareBtn : qc.Serializer.NODE,
 7     moreBtn : qc.Serializer.NODE,
 8     rankBtn : qc.Serializer.NODE
 9 });
10 
11 /**
12  * 初始化
13  */
14 Pause.prototype.awake = function() {
15     var self =this;
16     // 监听游戏暂停事件
17     this.addListener(qc.Koala.onPause, this.show, this);
18 
19     // 监听继续游戏按钮点击事件
20     this.addListener(this.continueBtn.onClick, this.onContinueBtnClick, this);
21 
22     // 监听重新开始游戏点击事件
23     this.addListener(this.restartBtn.onClick, this.onRestartBtnClick, this);
24 
25     // 监听分享按钮点击事件
26     this.addListener(this.shareBtn.onClick, function() {
27         qc.Koala.showShareMsg.dispatch();
28     }, this);
29 
30     // 监听更多游戏按钮点击事件
31     this.addListener(this.moreBtn.onClick, function() {
32         document.location.href = qc.Koala.logic.config.followHref;
33     }, this);
34 
35     // 监听排行榜按钮点击事件
36     this.addListener(this.rankBtn.onClick, this.onRankBtnClick, this);
37 };
38 
39 /** 重新开始游戏按钮点击后处理 */
40 Pause.prototype.onRestartBtnClick = function() {
41     // 派发游戏开始事件,并指定为重新开始
42     qc.Koala.onStart.dispatch(true);
43     // 隐藏死亡界面
44     this.hide();
45 };
46 
47 /**
48  * 继续游戏按钮点击后处理
49  */
50 Pause.prototype.onContinueBtnClick = function() {
51     // 设置游戏暂停状态
52     qc.Koala.logic.me.paused = false;
53 
54     // 派发继续游戏事件
55     qc.Koala.onContinue.dispatch();
56 
57     // 隐藏界面
58     this.hide();
59 };
60 
61 /**
62  * 排行榜按钮点击事件后处理
63  */
64 Pause.prototype.onRankBtnClick = function () {
65     if (qc.Koala.logic.me.userInfo &&
66         qc.Koala.logic.me.userInfo.subscribe) {
67         qc.Koala.onRankingClose.addOnce(this.show, this);
68 
69         qc.Koala.showRanking.dispatch();
70 
71         this.hide();
72     }
73     else {
74         //显示关注界面
75         qc.Koala.showFollowMsg.dispatch();
76     }
77 };
78 
79 /**
80  * 显示界面
81  */
82 Pause.prototype.show = function () {
83     this.gameObject.visible = true;
84 };
85 
86 /**
87  * 隐藏界面
88  */
89 Pause.prototype.hide = function () {
90     this.gameObject.visible = false;
91 };
View Code

当我们点击"关闭"按钮时,我们希望继续游戏。此时在Pause.js中的onContinueBtnClick方法中加入一个继续游戏的事件派发qc.Koala.onContinue.dispatch(),刚才暂停时,我们停止秋千与考拉的动作,此时,我们可以相应地在Scripts/ui/Koala.js中加入事件接收用于恢复游戏,加入的代码如下:

 1 var Koala = qc.defineBehaviour('qc.Koala.ui.Koala', qc.Behaviour, function() {
 2     // 秋千对象
 3     this.swingScript = null;
 4 
 5     // 考拉当前播放的动作
 6     this.currAnimation = 'stand';
 7 }, {
 8     // 相机节点
 9     camera : qc.Serializer.NODE,
10     // 特效节点
11     effect : qc.Serializer.NODE,
12     // 文本
13     labelImg : qc.Serializer.NODE,
14     // 分数
15     scoreImg : qc.Serializer.NODE,
16     // 死亡效果图片
17     dieImg : qc.Serializer.NODE,
18     // 刹车效果图片
19     brakeImg : qc.Serializer.NODE
20 });
21 
22 /**
23  * 初始化
24  */
25 Koala.prototype.awake = function () {
26 
27     // 监听游戏继续事件
28     this.addListener(qc.Koala.onContinue, this._continue, this);
29 };
30 
31 /**
32  * 继续游戏
33  * @method qc.Koala.ui.Koala#_continue
34  */
35 Koala.prototype._continue = function () {
36     if (this.currAnimation !== 'die')
37         this[this.currAnimation]();
38 };
View Code

 

7.2 游戏结束

游戏结束处理:在上一篇文章中我们在碰撞中讲到了当考拉碰到柱子的左边缘或者超出游戏边界时,则结束游戏;我希望游戏结束时,能够弹出游戏结束界面,界面上可以显示我这轮游戏的得分以及我历史的最高分,由于在手机上我们可以微信登录,所以我想游戏结束界面还应该有向好友分享的功能、查询排行榜功能、以及重玩一次的功能。最终效果图应该是这样的:

界面布局比较简单就不讲述了,读者们如果想知更多的界面布局信息也可以参考《界面布局》,需要讲述的是,当考拉碰到柱子左边缘或者超出游戏界面时,此时,在上一篇的脚本Main.js中的检测碰撞代码会返回对应死亡信息,如下面代码:

 1 Main.prototype._onDrop = function (vx0, vy0, t) {
 2     // 计算横向和纵向偏移值
 3     var preY = this.koala.y,
 4         deltaX = vx0 * t,
 5         deltaY = vy0 * t;
 6 
 7     // 设置考拉位置
 8     this.koala.x += deltaX;
 9     this.koala.y += deltaY;
10 
11     // 调整相机位置
12     this.adjustCamera(deltaX, deltaY);
13 
14     // 检测考拉位置
15     var result = this._checkCollide(preY);
16     if (result !== 0) {
17         // 移除定时器
18         this.game.timer.remove(this.dropTimer);
19         this.dropTimer = null;
20 
21         // 成功跳到下一个站台
22         if (result === 1) {
23             this._onStep();
24         }
25 
26         // 游戏结束
27         if (result < 0) {
28             this.gameOver(result);
29         }
30     }
31 };
32 
33 /**
34  * 检测考拉是否可以站在平台上
35  * @param  {number} preY - 考拉移动前的y轴位置
36  * @return {number} 返回值定义如下
37  *          1:落在跳台上;
38  *         -1:超出游戏边界;
39  *         -2:碰到跳台的左边缘;
40  *          0:还在掉落
41  */
42 Main.prototype._checkCollide = function(preY) {
43     var x = this.koala.x,
44         y = this.koala.y,
45         step = this._step.gameObject;
46 
47     // 判断是否落到跳台上
48     if (x > step.x &&
49         x < step.x + step.width &&
50         preY <= step.y + step.parent.y &&
51         y >= step.y + step.parent.y)
52         return 1;
53 
54     // 超出游戏边界,因为相机有跟着考拉在动,所以在这边不需要判断游戏屏幕x轴方向超边
55     if (y > this.gameObject.height + this.koala.height - this.pillarPool.parent.y)
56         return -1;
57 
58     // 判断与跳台左边缘碰撞
59     if (x > step.x &&
60         x < step.x + step.width &&
61         preY > step.y + step.parent.y)
62         return -2;
63 
64     return 0;
65 };
View Code

在上述代码中,我们可以判断如果result返回的值为负的,则此时我们就可以判断游戏结束并派发一个游戏结束的事件。在Main.js脚本代码中加入如下代码:

 1 /**
 2  * 游戏结束,并播放掉落动画
 3  * @param  {number} result - 游戏死亡类型
 4  *         -1:超出游戏边界;
 5  *         -2:碰到跳台的左边缘;
 6  */
 7 Main.prototype.gameOver = function(result) {
 8     // 设置游戏死亡状态
 9     qc.Koala.logic.me.isDie = true;
10 
11     // 禁止暂停按钮交互
12     this.pauseBtn.interactive = false;
13 
14     // 超出游戏边界
15     if (result === -1) {
16         qc.Koala.onGameOver.dispatch();
17         return;
18     }
19 
20     // 碰到跳台的左边缘
21     if (result === -2) {
22         // 播放死亡动作
23         var koalaScript = this.koala.getScript('qc.Koala.ui.Koala');
24         koalaScript.die(function() {
25             qc.Koala.onGameOver.dispatch();
26         });
27     }
28 };
View Code

相应的我们可以在Script/ui文件夹下创建脚本:GameOver.js,该脚本的主要功能是监听游戏结束事件的派发,分享功能、获取玩家历史最高分、查询排行榜及再玩一次,代码如下:

 1 var GameOver = qc.defineBehaviour('qc.Koala.ui.GameOver', qc.Behaviour, function() {
 2 }, {
 3     // 重新开始游戏按钮
 4     restartBtn : qc.Serializer.NODE,
 5     // 分享按钮
 6     shareBtn : qc.Serializer.NODE,
 7     // 更逗游戏按钮
 8     moreBtn : qc.Serializer.NODE,
 9     // 排行榜按钮
10     rankBtn : qc.Serializer.NODE,
11     // 记录更新
12     goalSign : qc.Serializer.NODE,
13     // 当前分数文本
14     scoreLabel : qc.Serializer.NODE,
15     // 最高分文本
16     bestLabel : qc.Serializer.NODE,
17     // 世界排名百分比
18     percentLabel : qc.Serializer.NODE
19 });
20 
21 GameOver.prototype.awake = function() {
22     // 监听游戏结束事件
23     this.addListener(qc.Koala.onGameOver, this.show, this);
24 
25     // 监听重新开始游戏点击事件
26     this.addListener(this.restartBtn.onClick, this.onRestartBtnClick, this);
27 
28     // 监听分享按钮点击事件
29     this.addListener(this.shareBtn.onClick, function() {
30         qc.Koala.showShareMsg.dispatch();
31     }, this);
32 
33     // 监听更多游戏按钮点击事件
34     this.addListener(this.moreBtn.onClick, function() {
35         document.location.href = qc.Koala.logic.config.followHref;
36     }, this);
37 
38     // 监听排行榜按钮点击事件
39     this.addListener(this.rankBtn.onClick, this.onRankBtnClick, this);
40 };
View Code

 

7.3 分享

分享功能的实现。根据策划要求,微信分享时,根据玩家所得的分数分享不同的内容,此时我们也可以将这些数据配置到Excel表中,在上一篇Excel表中添加一个sheet表取名share,添加的表格内容如下:

表中的min与max表示玩家的得分是不是在这个范围内,如果是则分享对应的内容。同样我们需要创建一个脚本解析share sheet表中的内容并且可以提供一个方法,根据提供的分数返回对应的内容,在Scripts/logic文件夹下创建脚本:Share.js,代码如下:

 1 var ShareInfo = function(data) {
 2     this.id = data.id * 1;
 3     this.min = data.min * 1;
 4     this.max = data.max * 1;
 5     this.max = this.max == null ? Infinity : this.max;
 6     this.content = data.content;
 7 };
 8 
 9 var Share = qc.Koala.logic.Share = function(excel) {
10     this.shareMap = {};
11 
12     if (!excel)
13         excel = qc.Island.game.assets.find('config');
14 
15     var sheet = excel.findSheet('share');
16 
17     for (var i in sheet.rows) {
18         var row = sheet.rows[i];
19         this.shareMap[row.id] = new ShareInfo(row);
20     }
21 
22     //qc.Koala.onScoreChange.add(this.share, this);
23 };
24 
25 Share.prototype = {};
26 Share.prototype.constructor = Share;
View Code

我们需要在入口脚本Koala.js的Koala.initLogic方法中将Share类实例化,如下:

 1 Koala.initLogic = function(excel, game) {
 2 
 3     // 设置游戏对象引用
 4     this.game = game;
 5 
 6     // 设置游戏帧率为60帧
 7     game.time.frameRate = 60;
 8 
 9     // 初始化系统配置
10     this.logic.config = new qc.Koala.logic.Config(excel);
11 
12     // 游戏相关数据逻辑类
13     this.logic.me = new qc.Koala.logic.Me();
14 
15     // 柱子相关逻辑类
16     this.logic.pillar = new qc.Koala.logic.Pillar(excel);
17 
18     // 风力值逻辑类
19     this.logic.wind = new qc.Koala.logic.Wind(excel);
20 
21     // 分享相关逻辑类
22     this.logic.share = new qc.Koala.logic.Share(excel);
23 
24     // 派发脚本准备就绪事件
25     this.onLogicReady.dispatch();
26 };
View Code

需要说明是,当我们点击分享成绩按钮时,此时我们需要点击手机屏幕右上角的分享功能,我们可以在Scripts/ui文件夹下的Welcome.js中的awake方法中加入代码,该代码用于从Share类中获取分享的内容,代码如下:

1 Welcome.prototype.awake = function() {
2     // 监听用户点击分享
3     this.addListener(wx.onShare, function(body) {
4         body.title = qc.Koala.logic.share.getContent(qc.Koala.logic.me.score);
5         body.imgUrl = qc.Koala.logic.config.shareIcon;
6         body.desc = "";
7     }, this);
8 };
View Code

游戏结束时,我们需要将玩家的得分与历史最高分作比较,如果高于历史最高分,则将该得分上传至服务器保存。需要说明的是:在游戏中,我们需要保存玩家的数据,数据分为两大类:

1、本地数据:例如历史最高分等。本地数据可以使用引擎提供的Storage功能来实现。前面的玩家分数管理用的就是Storage功能。

2、网络数据:如提交历史最高分、登录信息、排行榜信息等。需要说明的是,网络数据需要自行搭建服务器,服务器搭建好了之后,可以用引擎提供的AssetUtil功能来与服务器进行通信。搭建服务器代码就不做详述,大家可以选择自己擅长的语言搭建服务器,这里只讲解与服务器通信的接口。

在Scripts文件夹下创建脚本:Interactive.js,该脚本主要用于向服务器上传玩家数据。如在GameOver.js中有向服务器上传分数的代码,而Interactive.js就是提供一个接口。代码如下:

 1 var Interactive = qc.defineBehaviour('qc.Interactive', qc.Behaviour, function() {
 2     qc.interactive = this;
 3 }, {
 4     gameName: qc.Serializer.STRING,
 5     serverUrl: qc.Serializer.STRING
 6 });
 7 
 8 /**
 9  * 上传分数
10  * @param {string} rid - 用户唯一标示
11  * @param {string} token - 当前登陆用户的临时标示
12  * @param {number} scorers - 分数
13  * @param {func} callbackFunc - 回调函数
14  */
15 Interactive.updateScorers = function(rid, token, scorers, callbackFunc, onerror) {
16     var url = qc.interactive.serverUrl + "updateScorers03.php";
17     url += "?rid=" + rid;
18     url += "&token=" + token;
19     url += "&scorers=" + scorers;
20     url += "&gameName=" + qc.interactive.gameName;
21 
22     qc.AssetUtil.get(url, callbackFunc, onerror);
23 };
View Code

将该脚本挂载"欢迎界面"节点,其中ServerUrl为服务器路径。

在结束界面我们显示两个得分,分别是当前游戏得分,另一个是历史最高分,这两个数据我们可以从我们玩家分数管理脚本中获得,在GameOver.js中加入如下代码,该段代码的主要功能是显示当前分数及历史最高分,如果当前分高于历史最高分的话,则更新历史最高分:

 1 /**
 2  * 初始化界面
 3  */
 4 GameOver.prototype.initUI = function() {
 5     if (qc.Koala.logic.me.score === qc.Koala.logic.me.best) {
 6         this.goalSign.visible = true;
 7 
 8         // 判断当前分数是否超过历史最高分数
 9         qc.Interactive.updateScorers(
10             qc.Koala.logic.me.rid,
11             qc.Koala.logic.me.token,
12             qc.Koala.logic.me.best,
13             function(data) {
14                 // 更新分数成功
15                 console.log("更新分数成功");
16             }
17         );
18     }
19     else {
20         this.goalSign.visible = false;
21     }
22 
23     var score = qc.Koala.logic.me.score
24     this.scoreLabel.text = score + '';
25 
26     this.bestLabel.text = '最高分:' + qc.Koala.logic.me.best;
27 
28     var percent = qc.Koala.logic.percent.getPercent(score);
29     this.percentLabel.text = '你击败了全球' + percent + '%的玩家';
30 };
View Code

而再玩一次功能的实现,我们可以派发一个qc.Koala.onStart事件,即游戏重新开始,开始游戏时,也是通过派发一个qc.Koala.onStart事件,并将结束界面隐藏(即将结束界面的visible设置为false)实现比较简单。在GameOver.js脚本中加入代码:

1 /**
2  * 重新开始游戏按钮点击后处理
3  */
4 GameOver.prototype.onRestartBtnClick = function() {
5     // 派发游戏开始事件,并指定为重新开始
6     qc.Koala.onStart.dispatch(true);
7     // 隐藏死亡界面
8     this.hide();
9 };
View Code

查询排行榜的功能实现将在后续中详细讲述。

将上面的代码整合到一起,如下所示:

 1 var GameOver = qc.defineBehaviour('qc.Koala.ui.GameOver', qc.Behaviour, function() {
 2 }, {
 3     // 重新开始游戏按钮
 4     restartBtn : qc.Serializer.NODE,
 5     // 分享按钮
 6     shareBtn : qc.Serializer.NODE,
 7     // 更逗游戏按钮
 8     moreBtn : qc.Serializer.NODE,
 9     // 排行榜按钮
10     rankBtn : qc.Serializer.NODE,
11     // 记录更新
12     goalSign : qc.Serializer.NODE,
13     // 当前分数文本
14     scoreLabel : qc.Serializer.NODE,
15     // 最高分文本
16     bestLabel : qc.Serializer.NODE,
17     // 世界排名百分比
18     percentLabel : qc.Serializer.NODE
19 });
20 
21 GameOver.prototype.awake = function() {
22     // 监听游戏结束事件
23     this.addListener(qc.Koala.onGameOver, this.show, this);
24 
25     // 监听重新开始游戏点击事件
26     this.addListener(this.restartBtn.onClick, this.onRestartBtnClick, this);
27 
28     // 监听分享按钮点击事件
29     this.addListener(this.shareBtn.onClick, function() {
30         qc.Koala.showShareMsg.dispatch();
31     }, this);
32 
33     // 监听更多游戏按钮点击事件
34     this.addListener(this.moreBtn.onClick, function() {
35         document.location.href = qc.Koala.logic.config.followHref;
36     }, this);
37 
38     // 监听排行榜按钮点击事件
39     this.addListener(this.rankBtn.onClick, this.onRankBtnClick, this);
40 };
41 
42 /**
43  * 初始化界面
44  */
45 GameOver.prototype.initUI = function() {
46     if (qc.Koala.logic.me.score === qc.Koala.logic.me.best) {
47         this.goalSign.visible = true;
48 
49         // 判断当前分数是否超过历史最高分数
50         qc.Interactive.updateScorers(
51             qc.Koala.logic.me.rid,
52             qc.Koala.logic.me.token,
53             qc.Koala.logic.me.best,
54             function(data) {
55                 // 更新分数成功
56                 console.log("更新分数成功");
57             }
58         );
59     }
60     else {
61         this.goalSign.visible = false;
62     }
63 
64     var score = qc.Koala.logic.me.score
65     this.scoreLabel.text = score + '';
66 
67     this.bestLabel.text = '最高分:' + qc.Koala.logic.me.best;
68 
69     var percent = qc.Koala.logic.percent.getPercent(score);
70     this.percentLabel.text = '你击败了全球' + percent + '%的玩家';
71 };
72 
73 /**
74  * 重新开始游戏按钮点击后处理
75  */
76 GameOver.prototype.onRestartBtnClick = function() {
77     // 派发游戏开始事件,并指定为重新开始
78     qc.Koala.onStart.dispatch(true);
79     // 隐藏死亡界面
80     this.hide();
81 };
82 
83 
84 /**
85  * 显示界面
86  */
87 GameOver.prototype.show = function () {
88     this.initUI();
89     this.gameObject.visible = true;
90 };
91 
92 /**
93  * 隐藏界面
94  */
95 GameOver.prototype.hide = function () {
96     this.gameObject.visible = false;
97 };
View Code

将该脚本挂载到"游戏结束"节点,并将节点拖入到对应属性值上,如下图:

 

 

八、排行榜界面

在游戏结束的界面,我们点击排行榜,此时,我们希望出现一个排行榜,将玩家的得分、玩家的微信头像、玩家的排名及其它玩家的信息也显示到排行榜界面上,效果图如下:

排行榜界面的布局比较简单,与前面界面的布局类似。这里需要着重讲一下,排行榜界面的每一条关于玩家的头像、得分、排名及名字,我们可以做成一个预制,在显示时,需要在排行榜上显示多少玩家我们就可以产生多少预制。具体实现是:创建一个Empty Node节点取名rankingRow,依次创建玩家头像信息(在做预制时,可随意指定玩家头像信息,游戏中,我们可以通过微信获取相应玩家的头像信息并重置相应玩家的头像),排行名次、玩家名称及玩家得分,并将这些节点都挂载到"rankingRow"节点下,效果图如下:

不同的玩家有不同的玩家信息如头像、得分、名字等,为了能够正常的显示对应玩家的信息。在Scripts/ui文件夹下创建脚本:RankingRow.js,脚本代码如下:

 1 var RankingRow = qc.defineBehaviour('qc.Koala.ui.RankingRow', qc.Behaviour, function() {
 2 
 3 }, {
 4     rankingLabel : qc.Serializer.NODE,
 5     headIcon : qc.Serializer.NODE,
 6     nameLabel : qc.Serializer.NODE,
 7     score : qc.Serializer.NODE
 8 });
 9 
10 // 1, 2, 3名对应的排名文本相关颜色
11 RankingRow.COLORMAP = {
12     '1' : { color : new qc.Color('#F9FB02'), stroke : new qc.Color('#860001') },
13     '2' : { color : new qc.Color('#C5C6C1'), stroke : new qc.Color('#3A3436') },
14     '3' : { color : new qc.Color('#FEB266'), stroke : new qc.Color('#591B02') }
15 };
16 
17 // 排行榜默认的排名文本相关颜色
18 RankingRow.DEFAULTCOLOR = { color : new qc.Color('#FFFFFF'), stroke : new qc.Color('#A00F0A') };
19 
20 RankingRow.prototype.init = function(row) {
21     // 获取用户数据,并设置用户名和分数
22     this.nameLabel.text = row.name;
23     this.score.text = row.scorers + '';
24 
25     // 加载图片资源
26     var url = row.headurl;
27     var headIcon = this.headIcon;
28     if (url)
29         this.game.assets.loadTexture(row.rid, url, function(texture) {
30             headIcon.texture = texture;
31         });
32 
33     // 获取名次
34     var ranking = row.ranking || '100+',
35         rankLabel = ranking + '',
36         color = RankingRow.DEFAULTCOLOR;
37 
38     // 1,2,3名分别设置不同的排名文本颜色
39     if (ranking <= 3) {
40         // 获取文本内容及文本相关颜色
41         rankLabel = 'NO.' + ranking;
42         color = RankingRow.COLORMAP[ranking];
43     }
44     else {
45         // 设置排名文本字体大小
46         this.rankingLabel.fontSize = 52;
47     }
48 
49     // 设置排名文本颜色及描边颜色
50     this.rankingLabel.color = color.color;
51     this.rankingLabel.stroke = color.stroke;
52     this.rankingLabel.strokeThickness = 3;
53 
54     // 设置名次文本
55     this.rankingLabel.text = rankLabel;
56 };
View Code

将该脚本挂载到"rankingRow"节点,并将对应的节点拖入到对应的属性值,如下图:

 现在就有一个问题了,如果我们要显示的玩家个数大于排行榜界面大小时,我们将不能看到超出排行榜界面的玩家。此时,我们可以使用引擎提供的ScrollView用于解决此问题,具体做法是在"排行榜界面"节点下创建一个ScrollView节点,创建完成后我们可以看到如下信息:

其中Content属性值的含义是当我们创建玩家信息预制时,将玩家信息节点放到该节点下(图中是将玩家信息节点放到node节点下)。因为我们是要垂直滚动信息,所以在Vertical属性值上打钩,其它的属性具体含义可查看《ScrollView》。

前面我们已经把玩家预制做好了,但是怎么让它正确的显示出来,怎么去获取玩家的头像、分数、及排名等信息呢?我们可以这样做,把玩家的数据都上传至服务器并保存到数据库中,需要获取玩家的排名时,我们可以通过在前面的通信接口类脚本Interactive.js中加入下面代码:

 1 /**
 2  * 获取排行榜
 3  * @param {string} rid - 用户唯一标示
 4  * @param {string} token - 当前登陆用户的临时标示
 5  * @param {string} channel - 渠道
 6  * @param {func} callbackFunc - 回调函数
 7  */
 8 Interactive.getRank = function(rid, token, channel, callbackFunc, onerror) {
 9     var url = qc.interactive.serverUrl + "getRank03.php";
10     url += "?rid=" + rid;
11     url += "&token=" + token;
12     url += "&channel=" + channel;
13     url += "&gameName=" + qc.interactive.gameName;
14 
15     qc.AssetUtil.get(url, callbackFunc, onerror);
16 };
View Code

从而相应我们需要创建一个脚本:Ranking.js,该脚本的主要功能是请求玩家数据并解析,代码如下:

 1 var Ranking = qc.defineBehaviour('qc.Koala.ui.Ranking', qc.Behaviour, function() {
 2     this._rankingData = [];
 3 
 4     this._iconKeyList = [];
 5 }, {
 6     rankingList : qc.Serializer.NODE,
 7     rankingRowPrefab : qc.Serializer.PREFAB,
 8     ownRanking : qc.Serializer.NODE,
 9     waiting : qc.Serializer.NODE,
10     closeBtn : qc.Serializer.NODE
11 });
12 
13 Ranking.prototype.awake = function () {
14     this.addListener(qc.Koala.showRanking, this.show, this);
15 
16     this.addListener(this.closeBtn.onClick, this.close, this);
17 };
18 
19 Ranking.prototype.getRanking = function () {
20     // TODO 获取排行榜数据,监听到获取成功,调用getRankingSuccess方法
21     var self = this;
22     var me = qc.Koala.logic.me;
23     qc.Interactive.getRank(me.rid, me.token, me.channel, function(data) {
24         data = JSON.parse(data);
25         var rank = 0;
26         var rankTop = data.rankTop;
27         for (var i = 0; i < rankTop.length; i++) {
28             var u = rankTop[i];
29             if (u.rid === me.rid) {
30                 rank = i + 1;
31             }
32             u.ranking = i + 1;
33         }
34         data.selfRank = data.userData[0];
35         if (data.selfRank)
36             data.selfRank.ranking = rank;
37 
38         self.getRankingSuccess(data);
39     });
40 };
41 
42 Ranking.prototype.getRankingSuccess = function (data) {
43     this.waiting.stop();
44     this.waiting.visible = false;
45 
46     // 初始化排行榜列表
47     var n = this.rankingList.getScript('qc.Koala.ui.RankData');
48     n.rankData = data.rankTop;
49     n.dispatchDataChange();
50 
51 
52     // 初始化我的排名
53     this.initOwnRanking(data.selfRank);
54 };
55 
56 Ranking.prototype.initOwnRanking = function (row) {
57     var s = this.ownRanking.getScript('qc.Koala.ui.RankingRow');
58     s.init(row);
59 
60     this.ownRanking.visible = true;
61 };
62 
63 Ranking.prototype.show = function () {
64     this.gameObject.visible = true;
65 
66     this.waiting.visible = true;
67     this.waiting.playAnimation('zhuan', null, true);
68 
69     this.getRanking();
70 };
71 
72 Ranking.prototype.close = function () {
73     this.gameObject.visible = false;
74     this._rankingData.length = 0;
75 
76     this._iconKeyList.forEach(function(icon) {
77         this.game.assets.unload(icon);
78     }, this);
79 
80     this._iconKeyList.length = 0;
81 
82     //this.rankingList.content.removeChildren();
83 
84     qc.Koala.onRankingClose.dispatch();
85 };
View Code

将该脚本挂载到"排行榜界面"节点上,将对应的节点拖入对应的属性值上,如下图:

到这里,所有的游戏功能开发已经全部完成了。