天天看點

青瓷引擎之純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