• 青瓷引擎之纯JavaScript打造HTML5游戏第二弹——《跳跃的方块》Part 10(排行榜界面&界面管理)


    继上一次介绍了《神奇的六边形》的完整游戏开发流程后(可点击这里查看),这次将为大家介绍另外一款魔性游戏《跳跃的方块》的完整开发流程。

              (点击图片可进入游戏体验)

    因内容太多,为方便大家阅读,所以分多次来讲解。

    若要一次性查看所有文档,也可点击这里

    接上回(《跳跃的方块》Part 9

    (四)排行榜界面

    排行榜榜单元素

    排行榜的榜单也是一个TableView,所以我们先建立一个榜单元素的控制脚本:RankItem.js。

     1 // define a user behaviour
     2 var RankItem = qc.defineBehaviour('qc.JumpingBrick.RankItem', qc.Behaviour, function() {
     3     // need this behaviour schedule in editor
     4     //this.runInEditor = true;
     5 }, {
     6     positionImg : qc.Serializer.NODE,
     7     positionText : qc.Serializer.NODE,
     8     nameText : qc.Serializer.NODE,
     9     score : qc.Serializer.NODE,
    10     head : qc.Serializer.NODE,
    11     headBack : qc.Serializer.NODE,
    12     scoreBack : qc.Serializer.NODE
    13 });
    14 
    15 RankItem._position = [
    16     'first.png',
    17     'second.png',
    18     'third.png'
    19 ];
    20 
    21 RankItem._textTint = [
    22     0xffb16742,
    23     0xff2899a7,
    24     0xffa5b471,
    25     0xff876712
    26 ];
    27 
    28 RankItem._headBack = [
    29     'list_head_org.png',
    30     'list_head_blu.png',
    31     'list_head_green.png',
    32     'list_head_yel.png'
    33 ];
    34 
    35 RankItem._infoBack = [
    36     'list_bak_org.png',
    37     'list_bak_blu.png',
    38     'list_bak_green.png',
    39     'list_bak_yel.png'
    40 ];
    41 
    42 // Awake is called when the script instance is being loaded.
    43 RankItem.prototype.awake = function() {
    44 
    45 };
    46 
    47 RankItem.prototype.revoke = function() {
    48     var self = this;
    49     if (self.headKey) {
    50         // 清理资源
    51         self.game.assets.unload(self.headKey);
    52         self.headKey = null;
    53     }
    54 };
    55 
    56 // Update is called every frame, if the behaviour is enabled.
    57 RankItem.prototype.refreshData = function(index, data, cache) {
    58     // 更新信息
    59     var self = this;
    60     self.headBack.frame = RankItem._headBack[index < 4 ? (index - 1) : 3];
    61     self.scoreBack.frame = RankItem._infoBack[index < 4 ? (index - 1) : 3];
    62     if (index < 4) {
    63         self.positionImg.visible = true;
    64         self.positionImg.frame = RankItem._position[index - 1];
    65         self.positionText.visible = false;
    66         self.nameText.stroke = new qc.Color(RankItem._textTint[index - 1]);
    67         self.score.stroke = new qc.Color(RankItem._textTint[index - 1]);
    68     }
    69     else {
    70         self.positionImg.visible = false;
    71         self.positionText.visible = true;
    72         self.positionText.text = index.toString();
    73         self.nameText.stroke = new qc.Color(RankItem._textTint[3]);
    74         self.score.stroke = new qc.Color(RankItem._textTint[3]);
    75     }
    76 
    77     // 载入头像
    78     // 获取64 * 64的头像尺寸
    79     if (data.headurl) {
    80         if (self.headKey) {
    81             // 清理资源
    82             self.game.assets.unload(self.headKey);
    83         }
    84         self.headKey = data.headurl;
    85         self.game.assets.loadTexture(self.headKey, data.headurl + '64', function(assets) {
    86             self.head.texture = assets;
    87             if (cache) {
    88                 cache.dirty = true;
    89             }
    90         });        
    91     }
    92     self.nameText.text = data.name;
    93     self.score.text = data.score.toString();
    94 };

    创建榜单预制:sort_score.bin。并和脚本进行关联:

     

     其中mask使用Pixel模式,使用自己的本身图片的透明通道作为子节点的透明通道,设置如下:

     

    排行榜界面

    • 管理脚本 使用ViewTable来管理榜单节点,需要提供TableViewAdapter来提供数据。创建一个Announcement.js,用来提供数据并管理界面。内容如下:
      1 /**
      2  * 排行榜界面
      3  */
      4 var Announcement = qc.defineBehaviour('qc.JumpingBrick.Announcement', com.qici.extraUI.TableViewAdapter, function() {
      5 
      6 }, {
      7     closeButton: qc.Serializer.NODE,
      8     showPanel : qc.Serializer.NODE,
      9     myDesc : qc.Serializer.NODE,
     10     myPosition : qc.Serializer.NODE,
     11     myHeadPanel : qc.Serializer.NODE,
     12     myHead : qc.Serializer.NODE,
     13     myName : qc.Serializer.NODE,
     14     myScore : qc.Serializer.NODE
     15 });
     16 
     17 Announcement.prototype.awake = function() {
     18     var self = this,
     19         data = JumpingBrick.data;
     20     self.addListener(self.closeButton.onClick, self.returnToGameOver, self);
     21     self.addListener(self.gameObject.onClick, self.returnToGameOver, self);
     22     self.addListener(self.showPanel.onClick, function() {}, self);
     23     self.addListener(data.onRankUpdate, self.receiveRankData, self);
     24 };
     25 
     26 /**
     27  * 返回游戏结算界面
     28  */
     29 Announcement.prototype.returnToGameOver = function() {
     30     var self = this;
     31     if (self.headKey) {
     32         self.game.assets.unload(self.headKey);
     33     }
     34     JumpingBrick.uiManager.switchStateTo(qc.JumpingBrick.UIManager.GameOver);
     35 };
     36 
     37 // 请求排行榜数据
     38 Announcement.prototype.updateRank = function() {
     39     var data = JumpingBrick.data;
     40     data.queryRank();
     41 };
     42 
     43 /**
     44  * 收到排行榜数据
     45  */
     46 Announcement.prototype.receiveRankData = function(data) {
     47     var self = this;
     48     // 更新自己的信息
     49     var selfData = data.selfRank;
     50     if (!selfData) {
     51         self.myPosition.text = '请登录游戏后查看';
     52         self.myHeadPanel.visible = false;
     53         self.myName.visible = false;
     54         self.myScore.visible = false;
     55         self.myDesc.visible = false;
     56     }
     57     else {
     58         self.myPosition.text = selfData.ranking ? selfData.ranking.toString() : '未上榜';
     59         self.myHeadPanel.visible = true;
     60         self.myDesc.visible = true;
     61 
     62         // 获取64 * 64的头像尺寸
     63         if (selfData.headurl) {
     64             if (self.headKey) {
     65                 self.game.assets.unload(self.headKey);
     66             }
     67             self.headKey = selfData.headurl;
     68             self.game.assets.loadTexture(self.headKey, selfData.headurl + '64', function(assets) {
     69                 self.myHead.texture = assets;
     70             });        
     71         }
     72         self.myName.text = selfData.name;
     73         self.myScore.text = selfData.scorers.toString();
     74     }
     75 
     76     var rankTop = data.rankTop;
     77     self.rankTop = rankTop;
     78 
     79     self.dispatchDataChange();
     80 };
     81 
     82 
     83 /**
     84  * 获取表格大小,x、y同时只能有一个为Infinity
     85  */
     86 Announcement.prototype.getTableSize = function() {
     87     return { x: 1, y: this.rankTop ? this.rankTop.length : 0 };
     88 };
     89 
     90 /**
     91  * 根据在Table中的点返回对应的单元格
     92  * @param  {number} x - x轴坐标
     93  * @param  {number} y - y轴坐标
     94  */
     95 Announcement.prototype.findCellWithPos = function(x, y) {
     96     return {
     97         x: Math.floor(x / 540),
     98         y: Math.floor(y / 90)
     99     };
    100 };
    101 
    102 /**
    103  * 获取节点的显示位置
    104  */
    105 Announcement.prototype.getCellRect = function(col, row) {
    106     return new qc.Rectangle(col * 540, row * 90, 540, 90);
    107 };
    108 
    109 /**
    110  * 节点处于不可见时,回收节点,
    111  * @param  {qc.Node} cell - 节点
    112  * @param  {number} col - 所在列
    113  * @param  {number} row - 所在行
    114  */
    115 Announcement.prototype.revokeCell = function(cell, col, row) {
    116     cell.getScript('qc.JumpingBrick.RankItem').revoke();
    117 };
    118 
    119 /**
    120  * 节点处于可见时,创建节点,
    121  * @param  {qc.Node} cell - 节点
    122  * @param  {number} col - 所在列
    123  * @param  {number} row - 所在行
    124  */
    125 Announcement.prototype.createCell = function(cell, col, row) {
    126     if (this.rankTop) {
    127         cell.getScript('qc.JumpingBrick.RankItem').refreshData(row + 1, this.rankTop[row]);
    128     }
    129 };
    • 排行榜根节点 排行榜界面是一个固定大小的窗口,如果还是按游戏的方式以高度为准,可能在有些设备上就会超出屏幕区域。 所以,为了排行榜,需要再建立一个UIRoot,命名为announcement,Manual Type类型为Expand,建议的宽高还是设计使用的(640, 960)。 如图所示:

     为了适应屏幕旋转,还是需要为announcement节点添加一个锁屏的组件。如图所示:

    • 界面展示及脚本关联 在锁屏组件下开始拼界面,并将Announcement.js加到announcement节点上。如图所示: 

     

    其中tableView的脚本挂载scrollView节点上,配置如下:

     

    五)界面管理

    基本界面都已经做好,将这些界面节点同UIManager关联起来,设置如图所示:

     

    这样界面部分也就都完成了。

    结束语

    到这里,所有的游戏功能开发已经全部完成了。总体的开发思路和时间安排是这样:

    1. 从设计方案出发,提炼配置。
    2. 优先完成主体玩法,尽早进行玩法迭代。
    3. 再逐步完善数据处理和界面逻辑。

    感谢各位坚持看到最后,《跳跃的方块》到此就分享完了。若对工程示例或引擎的使用有任何问题,请一定告诉我们,我们会不断努力,继续完善。以后还将陆续分享其他好游戏的开发经验,望大家继续关注,谢谢!

    其他相关链接

    开源免费的HTML5游戏引擎——青瓷引擎(QICI Engine) 1.0正式版发布了!

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

    青瓷引擎之纯JavaScript打造HTML5游戏第二弹——《跳跃的方块》Part 1

     
     
  • 相关阅读:
    js-禁止微信H5页面点击右上角菜单时出现“复制链接”,且分享仅支持微信分享
    js-获取用户移动端网络类型:wifi、4g、3g、2g...
    小程序-云开发部署流程(步骤二)
    小程序-(报错)请使用 2.2.3 或以上的基础库以使用云能力(步骤一)
    解决iOS10的Safari下Meta设置user-scalable=no无效的方法
    领域驱动, 事件驱动,测试驱动
    spring web项目中整合netty, akka
    why rpc
    nginx配置https证书
    org.apache.http.NoHttpResponseException
  • 原文地址:https://www.cnblogs.com/qici/p/5105791.html
Copyright © 2020-2023  润新知