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

(点击图片可进入试玩)

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

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 };

在该代码中有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 };

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

菜单界面具体布局我就不详述了,可以参看前两篇文章的界面布局,也可以查看更详细的界面布局信息《界面布局》。前面我们讲过,当按下暂停按钮时,该菜单界面也会弹出来。我们可以创建一个脚本: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 };

当我们点击"关闭"按钮时,我们希望继续游戏。此时在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 };

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 };

在上述代码中,我们可以判断如果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 };

相应的我们可以在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 };

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;

我们需要在入口脚本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 };

需要说明是,当我们点击分享成绩按钮时,此时我们需要点击手机屏幕右上角的分享功能,我们可以在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 };

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

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 };

将该脚本挂载"欢迎界面"节点,其中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 };

而再玩一次功能的实现,我们可以派发一个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 };

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

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

 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 };

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

八、排行榜界面

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

排行榜界面的布局比较简单,与前面界面的布局类似。这里需要着重讲一下,排行榜界面的每一条关于玩家的头像、得分、排名及名字,我们可以做成一个预制,在显示时,需要在排行榜上显示多少玩家我们就可以产生多少预制。具体实现是:创建一个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 };

将该脚本挂载到"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 };

从而相应我们需要创建一个脚本: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 };

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

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

时间: 2024-10-24 21:55:12

JS开发HTML5游戏《悠悠考拉》(三)的相关文章

JS开发HTML5游戏《神奇的六边形》(四)

近期出现一款魔性的消除类HTML5游戏<神奇的六边形>,今天我们一起来看看如何通过开源免费的青瓷引擎(www.zuoyouxi.com)来实现这款游戏. (点击图片可进入游戏体验) 因内容太多,为方便大家阅读,所以分成四部分来讲解. 本文为第四部分,主要包括: 16.分数往上飘动画 17.形状飞入动画 18.其他动画表现添加 19.游戏结束界面 20. 添加LOGO 21. 渲染优化 若要一次性查看所有文档,也可点击这里. 十六. 分数往上飘的动画 在表现加分时,分数会有个缩放的效果,然后往上

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

悠悠考拉是一款好玩而且又考验判断与反应能力的游戏,让我们一起来看看通过开源免费的青瓷引擎是如何来实现这款游戏. (点击图片可进去试玩) 源代码与资源下载 本文共有三部分内容,本篇文章为第一部分,主要内容如下: 1.游戏功能分析 2.游戏主体模块的设计 一.游戏功能分析 根据游戏设定,解析出游戏的主要功能,分解成每个功能模块,然后制订每个功能模块代码结构,如下图所示: 二.游戏主体模块的设计 2.1 考拉 从游戏最终的界面效果我们可知该游戏的主体模块为考拉.藤条.柱子.下面分别介绍每个主体模块:

JAVASCRIPT开发HTML5游戏--斗地主(网络对战PART4)

继之前用游戏引擎(青瓷引擎)做了斗地主单机版游戏之后,这里分享下使用socket.io来实现网络对战,代码可已放到github上,在此谈谈自己整个的开发思路吧. 客户端代码 服务端代码 (点击图片进入游戏体验) 前文链接: javascript开发HTML5游戏--斗地主(单机模式part1) javascript开发HTML5游戏--斗地主(单机模式part2) javascirpt开发HTML5游戏--斗地主(单机模式part3) 本文章为网络对战第一部分内容.主要内容如下: 简介 服务端项

HTML5游戏实战(4): 20行代码实现FlappyBird

这个系列很久没有更新了.几个月前有位读者调侃说,能不能一行代码做一个游戏呢.呵呵,接下来一段时间,我天天都在想这个问题,怎么能让GameBuilder+CanTK进一步简化游戏的开发呢.经过几个月的努力,虽然还是做不到一行代码做一个游戏,但是GameBuilder的功能已经有了质的突破了.今天我们用FlappyBird为例介绍一下用GameBuilder +CanTK开发游戏的方法,整个游戏用了不到20行代码. CanTK(Canvas ToolKit)是一个开源的游戏引擎和APP框架,是开发H

HTML5游戏实战(2):90行代码实现捕鱼达人

捕鱼达人是一款非常流行的游戏,几年里赚取了数以千万的收入,这里借用它来介绍一下用Gamebuilder+CanTK开发游戏的方法.其实赚钱的游戏未必技术就很难,今天我们就仅用90来行代码来实现这个游戏. CanTK(Canvas ToolKit)是一个开源的游戏引擎和APP框架,是开发HTML5游戏或者APP的利器,如果你喜欢它,请在github上给它加星,您的支持是我们努力的动力:https://github.com/drawapp8/cantk 0.先Show一下最终成果: 在线运行:htt

HTML5游戏实战(3): 60行代码实现水平跑酷游戏

跑酷游戏无疑是目前最受欢迎的游戏类型之一,3D跑酷游戏可能比较难做一点(这个我不懂),2D跑酷却是非常容易的,只要有美术资源,做一个<天天酷跑>这类流行游戏也并非是什么难事. 这里通过一个松鼠跑酷的游戏介绍一下用Gamebuilder+CanTK开发游戏的方法,这个游戏的主场景仅用了60来行代码. CanTK(Canvas ToolKit)是一个开源的游戏引擎和APP框架,是开发HTML5游戏和APP的利器,如果你喜欢它,请在github上给它加星,您的支持是我们努力的动力:https://g

【Html5游戏开发 with LufyLegend.js 之一】一览全局函数 &amp; LGlobal静态类

一,前言 最近开始学习lufylegend.js,它是一款基于MIT协议的开源HTML5游戏引擎,目前使用Canvas渲染,2.0后会增添WebGL渲染.与其他的引擎相比,最大的特点就是模仿了ActionScript 3.0的语法,当然这只是一个特点,不会ActionScript对于学习lufylegend.js也没有什么坏的影响,我就是一个很好的例子(*_^),只不过如果你接触过ActionScript,那使用lufylegend.js的时候可能会顺手一些.以下是关于lufylegend.js

HTML5游戏开发引擎Pixi.js新手入门讲解

在线演示 本地下载 ?这篇文章中,介绍HTML5游戏引擎pixi.js的基本使用. 相关代码如下: Javascript 导入类库:(使用极客的cdn服务:http://cdn.gbtags.com) <scripttype="text/javascript"src="http://cdn.gbtags.com/pixi.js/1.6.1/pixi.js"></script> 引擎使用: .... .... 阅读原文:HTML5游戏开发引擎P

HTML5游戏开发-扫雷及其算法研究

吕蒙曰:士隔三月[1],当刮目相看.所以,在下在这三月中发奋图强,花了约莫8节信息课的时间研究扫雷.呜呼,由于在下才能尚且不足,所以也就只能勉强打过中级难度的吧.不过,一边玩的同时,我还一边对扫雷这个游戏的制做方法构思了一下.所以说,本文中的算法完全是凭借自己对扫雷游戏规则的总结而自行研发出来的,倘若和MS的扫雷玩法有些出入,还望各位看官见谅. [1]出自<孙权劝学>,原文为"士别三日",由于在下这三个月来都不曾发表博客,所以引申到"士隔三月",各位看官