關於egret開發H5頁游,資源管理和加載的一點看法。
一 多json文件管理
二 資源歸類和命名
三 exml文件編寫規范
四 資源預加載、分步加載、偷載
五 資源文件group分組
六 ResUtils,多json文件管理類
七 ResUtils,資源組加載管理類
八 開發中遇到的一點問題
一 多json文件管理
當多人協作時,添加資源時常因為資源文件修改而導致svn沖突。
根據各人不同負責的模塊,將資源文件划分。
原來的
default.res.json
可以修改為
login.res.json
hall.res.json
game.res.json
sound.res.json
...
新建的文件需要配置一下,否則無法使用,配置方法見下面《八 開發中遇到的一點問題》。
二 資源歸類和命名
asset文件夾下,分類存放圖片。根據項目可自行划分。
為了防止多個文件中資源命名沖突,軟件只有檢測單文件中命名沖突,沒有自動檢測多文件命名沖突的功能。
所以可以加前綴解決。
login_loginbtn
login_logo
hall_roombg
hall_setbtn
game_bg
game_option
....
對於公用的圖片,尤其是login、hall、game中通用的按鈕和背景,可以單獨放在common資源組中,以備復用。
一來防止圖片多次加載,導致發包體積過大。二來修改按鈕圖片時,只需修改一處即可。
com_btn0
com_btn1
com_box0
com_box1
com_panelbg
...
三 exml文件編寫規范
編寫Exml文件時,為了二次修改,便於查找閱讀,可以效仿Flash多圖層的存放元件。
優點:
1. 當查找時,可以根據圖層名查找到圖片或文本。
2. 點擊圖層左側眼鏡,可隱藏該圖層的所有組件。
缺點:
1. 單擊選擇時,只能選擇最上層Group,而不能穿透Group選擇到另一層的組件...比如直接點擊界面是無法選擇Logo這個文本的。(注:wing3.0已經解決了這個問題)
2. group折疊時,無法一目了然當前所有組件。
四 資源預加載、實時加載、偷載
1. 黑屏
在進入preload預加載界面時,此時會有短暫的黑屏。可將html背景色設置為白色或其他顏色,感覺比黑屏要好一些。
2. 預加載
打開場景。 從preload進入login場景時,預先加載login界面的資源,給出加載loading界面,加載完成后再進入login。
3. 實時加載
預加載只加載用戶一進入場景時所見資源,其他該場景資源,比如彈框資源等,在使用時再實時加載。這樣可以大大減少用戶進入場景等待時間。
在打開彈框時,給出loading動畫,加載完后再顯示彈框。
彈框除了資源,還有http請求顯示的數據,這個請求也需要時間等待,未返回數據前,界面數據為空,或者顯示之前請求的數據,等加載完成再顯示更新。
如下圖,當http請求無返回數據時,界面是空的,或者是之前請求的數據。
當http請求返回數據時,再更新該彈框。
3. 偷載
進入某場景后,用戶可能不會馬上進行某些操作。進入場景后即刻加載該場景所用資源。不用顯示loading畫面,在用戶不知的情況完成加載。
五 資源文件group分組
資源文件可按照場景、彈框、通用來分組。
場景必須資源:preload、login、hall、game
大廳中彈框資源:option、rank、mission、skill、roleInfo
聲音資源:sound
通用資源:common
根據項目可自行細分。
資源組划分的目的,就是將資源分類管理,方便在加載時使用。
在進入login場景時,只加載login資源組。打開設置彈框時,只加載option資源組。
六 ResUtils,多json文件管理類
六、七代碼部分參考了Egret論壇某人的代碼,略微修改了一下。首先感謝這位仁兄分享自己的代碼,其次我忘了他叫啥了- -! 。。。
ResUtils.ts
/** * 資源加載工具類, * 支持多個resource.json文件加載 */
class ResUtils { private static instance:ResUtils; private _configs: Array<any>; private _onConfigComplete: Function; private _onConfigCompleteTarget: any; public static getInstance():ResUtils{ if(this.instance == null){ this.instance = new ResUtils(); } return this.instance; } /** * 構造函數 */
public constructor() { this._configs = new Array<any>(); } /** * 添加一個配置文件 * @param jsonPath resource.json路徑 * @param filePath 訪問資源路徑 */
public addConfig(jsonPath: string,filePath: string): void { this._configs.push([jsonPath,filePath]); } /** * 開始加載配置文件 * @param $onConfigComplete 加載完成執行函數 * @param $onConfigCompleteTarget 加載完成執行函數所屬對象 */
public loadConfig($onConfigComplete: Function,$onConfigCompleteTarget: any): void { this._onConfigComplete = $onConfigComplete; this._onConfigCompleteTarget = $onConfigCompleteTarget; this.loadNextConfig(); } /** * 加載 */
private loadNextConfig(): void { //加載完成
if(this._configs.length == 0) { this._onConfigComplete.call(this._onConfigCompleteTarget); this._onConfigComplete = null; this._onConfigCompleteTarget = null; return; } var arr: any = this._configs.shift(); RES.addEventListener(RES.ResourceEvent.CONFIG_COMPLETE,this.onConfigCompleteHandle,this); RES.loadConfig(arr[0],arr[1]); } /** * 加載完成 * @param event */
private onConfigCompleteHandle(event: RES.ResourceEvent): void { RES.removeEventListener(RES.ResourceEvent.CONFIG_COMPLETE,this.onConfigCompleteHandle,this); this.loadNextConfig(); } }
//加載多個資源文件
ResUtils.getInstance().addConfig("resource/test.json","resource/"); ResUtils.getInstance().addConfig("resource/test2.json","resource/"); ResUtils.getInstance().loadConfig(this.onConfigComplete, this);
七 ResUtils,資源組加載管理類
ResUtils.ts
/** * 資源加載
* 支持單個或多個資源組加載 */
class ResUtils extends BaseClass { /**保存資源組名*/
private groups: any; /** * 構造函數 */
public constructor() { super(); this.groups = {}; RES.addEventListener(RES.ResourceEvent.GROUP_COMPLETE,this.onResourceLoadComplete,this); RES.addEventListener(RES.ResourceEvent.GROUP_PROGRESS,this.onResourceLoadProgress,this); RES.addEventListener(RES.ResourceEvent.GROUP_LOAD_ERROR,this.onResourceLoadError,this); } /** * 加載資源組,靜默加載(無回調函數) * @group 資源組(支持字符串和數組) */
public loadGroupQuiet(group){ var groupName:string = this.combGroupName(group); RES.loadGroup(groupName); } /** * 加載資源組,帶加載完成回調 * @group 資源組(支持字符串和數組) * @onComplete 加載完成回調 * @thisObject 回調執行對象 * @priority 優先級 */
public loadGroup(group, onComplete:Function, thisObject:any, priority:number = 1){ var groupName:string = this.combGroupName(group); this.groups[groupName] = [onComplete,null,thisObject]; RES.loadGroup(groupName); } /** * 加載資源組,帶加載進度 * @group 資源組(支持字符串和數組) * @onComplete 加載完成回調 * @onProgress 加載進度回調 * @thisObject 回調執行對象 */
public loadGroupWithPro(group ,onComplete: Function,onProgress: Function,thisObject: any): void { var groupName:string = this.combGroupName(group); this.groups[groupName] = [onComplete,onProgress,thisObject]; RES.loadGroup(groupName); } /** * 組合資源組名。單個資源組直接返回。多個資源組則重新命名。 * @group 新資源組名 */
private combGroupName(group){ if(typeof(group) == "string"){ return group; }else{ var len = group.length; var groupName:string = ""; for(var i=0;i<len;i++){ groupName += group[i]; } RES.createGroup(groupName,group,false); //是否覆蓋已經存在的同名資源組,默認 false
return groupName; } } /** * 資源組加載完成 */
private onResourceLoadComplete(event: RES.ResourceEvent): void { var groupName: string = event.groupName; console.log("資源組加載完成:" + groupName); if(this.groups[groupName]) { var loadComplete: Function = this.groups[groupName][0]; var loadCompleteTarget: any = this.groups[groupName][2]; if(loadComplete != null) { loadComplete.call(loadCompleteTarget); } this.groups[groupName] = null; delete this.groups[groupName]; } } /** * 資源組加載進度 */
private onResourceLoadProgress(event: RES.ResourceEvent): void { var groupName: string = event.groupName; if(this.groups[groupName]) { var loadProgress: Function = this.groups[groupName][1]; var loadProgressTarget: any = this.groups[groupName][2]; if(loadProgress != null) { loadProgress.call(loadProgressTarget,event); } } } /** * 資源組加載失敗 */
private onResourceLoadError(event: RES.ResourceEvent): void { console.log(event.groupName + "資源組有資源加載失敗"); this.onResourceLoadComplete(event); } }
測試加載
var res:ResUtils = ResUtils.getInstance(); //res.loadGroupQuiet("login"); //res.loadGroup("login", ()=>{ console.log("login load complete")}, this); //res.loadGroupWithPro("login", // ()=>{console.log("login load complete")}, // (e:RES.ResourceEvent)=>{console.log("login progress",e.itemsLoaded,e.itemsTotal)},this);
res.loadGroupQuiet(["preload","login"]);
八 開發中遇到的一點問題
但是在egret wing2.5中,default.des.json改名后,就會使用不正常了。
找不到路徑下的資源。
解決以上問題,需要在 項目-項目屬性-資源 中添加配置文件。