通過前面的開始界面基本上了解了eui的使用方法,可以簡單快速的制作一個UI界面,本篇使用第二界面選關界面展示更為難一點的代碼控制,來展現關卡地圖的內容,請確保素材和資源完整,可以在前面的教程中找到下載。
選關界面和開始界面不太一樣,請參考開篇的結構圖,需要一個推進式上下拉動的地圖界面,創建基本的exml和開始界面是一樣的,這里的名字叫“SceneLevelsSkin”,在組件庫中把Scroller組件拖進去並給其下屬內容命名group_levels,用來承載地圖內容,最后加一個返回按鈕。
<?xml version='1.0' encoding='utf-8'?> <e:Skin class="SceneLevelsSkin" width="720" height="1136" xmlns:e="http://ns.egret.com/eui" xmlns:w="http://ns.egret.com/wing" > <e:Scroller top="0" bottom="0" right="0" left="0"> <e:Group id="group_levels"/> </e:Scroller> <e:Button id="btn_back" x="607" y="1047"> <e:skinName> <e:Skin states="up,down,disabled"> <e:Image width="100%" height="100%" source="BackBtn_png" source.down="BackBtn1_png"/> <e:Label id="labelDisplay" horizontalCenter="0" verticalCenter="0"/> </e:Skin> </e:skinName> </e:Button> </e:Skin>
下面准備制作關卡圖標,關卡圖標對應的有主要的兩種狀態:開啟和未開啟,正好可以使用Button組件來實現,通過控制enabled實現開啟和未開啟狀態對應,按照之前的做法拖拽的創建一個按鈕,然后輸入數字就可以當成關卡按鈕了,可是問題來了,本游戲中有400多關,一個一個擺放累死不償命的,所以,有幾種做法是:分頁、分組、用代碼生成,分頁的方式不能實現地圖的拖拽效果,所以本項目中,我們用代碼控制去管理創建按鈕。
為了更快的控制和更好的理解教程,在這里,使用自定義的button皮膚來實現LevelIcon的效果,先創建一個基於eui.Button組件的LevelIconSkin皮膚,大小設置為77x77,
然后為各種狀態添加圖片和顯示設置,在所有狀態中增加一個Label用來顯示關卡的數字,具體拖拽細節不再啰嗦,效果如下:
<?xml version='1.0' encoding='utf-8'?> <e:Skin class="LevelIconSkin" states="up,down,disabled" width="77" height="77" xmlns:e="http://ns.egret.com/eui" xmlns:w="http://ns.egret.com/wing"> <e:Image source="gs_select_1_png" horizontalCenter="0" verticalCenter="0" includeIn="up,down"/> <e:Image source="gs_select_dis_png" includeIn="disabled" horizontalCenter="0" verticalCenter="0"/> <e:Label id="lb_level" text="100" horizontalCenter="0" verticalCenter="0"/> </e:Skin>
保存一下,然后可以在界面中拖進去一個button組件,直接在皮膚中選擇就可以看到顯示效果了,
為了控制和便於操作,增加一個LevelIcon.ts ,這里使用了get和set創建了一個屬性來標記關卡數字
class LevelIcon extends eui.Button{ private lb_level:eui.Label; public constructor() { super(); this.skinName = "src/Game/LevelIconSkin.exml"; } public get Level():number{ return parseInt(this.lb_level.text); } public set Level(value:number){ this.lb_level.text = value.toString(); } }
下面就是SceneLevels.ts的代碼,會用上前面的SceneLevelsSkin.exml,請確保已經准備完成了SceneLevelsSkin.exml和LevelIcon:
class SceneLevels extends eui.Component { private btn_back: eui.Button; private group_levels:eui.Group; public constructor() { super(); this.skinName = "src/Game/SceneLevelsSkin.exml"; this.btn_back.addEventListener(egret.TouchEvent.TOUCH_TAP,this.onclick_back,this); //創建地圖選項 var row = 20; var col = 10; var spanx = 720 / col; //計算行x間隔 var spany = 1136 / row; //計算列y間隔 var group = new eui.Group();//地圖背景 group.width = 720; group.height = (spany * 400 );//算出最大尺寸 //填充背景 for(var i = 0;i <= (group.height / 1138) ;i++) { var img = new eui.Image(); img.source = RES.getRes("GameBG2_jpg"); img.y = i * 1138; img.touchEnabled = false; this.group_levels.addChildAt(img,0); } //以正弦曲線繪制關卡圖標的路徑 for(var i = 0; i<400;i++){ var icon = new LevelIcon(); icon.Level = i + 1; icon.y = spany * i /2; icon.x = Math.sin(icon.y / 180 * Math.PI) * 200 + group.width / 2; icon.y += spany * i /2; icon.y = group.height - icon.y - spany; group.addChild(icon); icon.addEventListener(egret.TouchEvent.TOUCH_TAP,this.onclick_level,this); } //開啟位圖緩存模式 group.cacheAsBitmap = true; this.group_levels.addChild(group); //卷動到最底層 this.group_levels.scrollV = group.height - 1100; } private onclick_back() { } private onclick_level(e:egret.TouchEvent){ var icon = <LevelIcon>e.currentTarget; console.log(icon.Level); } }
為了看起來好看,上面代碼中沒有使用簡單的代碼排列關卡,而是使用了正弦曲線描繪,當然細節上仍需要調整,要知道另外一個《瘋狂猜歌名》的關卡按鈕可是一個一個擺放的,200多關呢。現在所有的按鈕都是開啟狀態,點擊一下輸出里看到點到的按鈕數字,上下可以拖動,已經達到了我們的目的
但是,細節上仍然可以再處理一下,當我們點擊那個按鈕時候,就會有個指示來標記當前的選定,在正式游戲中,都是 選定=>進入 這樣的體驗流程,所以,增加一個arrow,這里正好當初的素材中多了一個本來用來做關卡翻頁效果的廢棄資源,直接用它來做素材,聲明類里一個對象:
private img_arrow:eui.Image;
在構造方法里增加:
//跟蹤箭頭 this.img_arrow = new eui.Image(); this.img_arrow.source = RES.getRes("PageDownBtn_png"); this.img_arrow.anchorOffsetX = 124 / 2 - group.getChildAt(0).width / 2; this.img_arrow.anchorOffsetY = 76; this.img_arrow.touchEnabled = false; this.img_arrow.x = group.getChildAt(0).x; this.img_arrow.y = group.getChildAt(0).y; group.addChild(this.img_arrow);
在onclick_level方法里增加:
private onclick_level(e:egret.TouchEvent){ var icon = <LevelIcon>e.currentTarget; console.log(icon.Level); this.img_arrow.x = icon.x; this.img_arrow.y = icon.y; }
最后看看效果怎么樣?打開Main.ts,在修改startCreateScene方法,然后運行看看吧。
/** * 創建場景界面 * Create scene interface */ protected startCreateScene(): void { this.addChild(new SceneLevels()); }
本篇中使用了eui創建自定義按鈕組件,卷動視圖的應用,並通過代碼方式來控制界面元素。
本篇項目源代碼:源代碼下載 (由於資源過大,沒有resource文件夾,請參考之前的文章單獨下載素材)