文章按照做者調研和開發順序初步介紹和理解了微信小遊戲和白鷺引擎,併產出了基於白鷺引擎的應用初始化程序egret-wechat-start。 如下是正文——
javascript
wx.createCanvas() 建立畫布,
getContext獲取對象後,剩下的就是對原生canvas接口的操做了。 理解到這一點以後,咱們就會發現小遊戲僅僅是封裝了下建立畫布的接口,剩下的就是用戶須要在畫布裏用原生canvas繪製了,並無提供其餘方便開發的功能。到此咱們再看看微信開發者工具建立小遊戲項目時,初始化的一個飛機遊戲的demo。
是如上圖的一個很簡單的遊戲,說下這個遊戲的大體實現邏輯:
canvas.addEventListener('click', (event)=>{
獲取event對象x,y
獲取 buttonA:x,y,width,height
判斷是否點擊
獲取 buttonB:x,y,width,height
判斷是否點擊
})
一個彈窗上面的按鈕點擊,反而把彈框下面的按鈕也點擊到了,這不符合預期,那要解決這個問題,咱們還須要一個層級管理器,根據層級判斷誰應該觸發,誰不該該觸發。 目前就事件處理咱們須要實現兩個基礎功能,事件監聽池和元素對象層級管理器,由於事件只能綁定在canvas上,canvas事件觸發之後,須要一個事件監聽池來遍歷監聽池裏的元素對象並判斷誰被觸發了(監聽池也會隨時增減監聽對象),監聽池獲取的依然是一個對象集,層級管理器判斷出對象集裏最上層的元素進行觸發。 想一想功能好像愈來愈複雜了。 目前還沒考慮完善,不只僅是事件處理問題,還可能會有其它大大小小的問題。 用canvas原生開發,工做量可能會很是大。 因此這樣看來,本身把這些實現了是不科學的,須要使用三方引擎開發才行。 由於兩年前用過白鷺引擎,因此就事件監聽和層級管理這個事情,我知道白鷺引擎已經實現了,除開事件,圖形繪製,動畫等等印象中白鷺都提供了,若是用引擎開發小遊戲實現成本被大大下降。html
開發中主要的核心apijava
Texture Merger 可將零散紋理拼合爲整圖,同時也能夠解析SWF、GIF動畫,製做Egret位圖文本,導出可供Egret使用的配置文件。 我主要使用其中的精靈圖功能,把圖片集合到一張圖上,而且會同時導出一個json的精靈圖的在圖片中的位置等配置信息git
擴展庫在覈心引擎功能之上提供了更高級的api,擴展庫在引擎配置文件裏配置好之後,會直接把方法和對象載入到egret全局對象中,目前我主要使用的擴展庫有:github
你能夠快速瀏覽一遍官方教程,以便更好對下文有所理解,http://developer.egret.com/cn/github/egret-docs/Engine2D/getStarted/helloWorld/index.html 。 文章不是教程因此會省略掉那些白鷺官網裏的教程。 如今咱們使用egret launcher建立一個初始化項目,初始化後的文件結構以下圖,我展開了resource和src文件夾,由於咱們須要操做的主要是這兩個文件夾,resource文件夾主要是存放靜態資源,咱們的代碼都在src裏,白鷺使用的是typescript。web
在wing工具裏,咱們能夠立刻開啓調試,就能夠在瀏覽器或者它自帶的容器裏預覽效果。 main.ts是啓動文件,main中首先使用await對resource中定義好的圖片資源進行了預加載,因此預覽開始後會出現loading效果,loading的繪製是寫在src中LoadingUI.ts,圖片加載完成之後,main裏直接建立了下圖2的頁面,而且添加了一個按鈕,點擊後會出現一個彈窗。 效果以下圖。typescript
至此,初始化demo已經告訴了咱們如何繪製圖像和綁定事件了,以下圖,我只截取了click按鈕的代碼,圖像繪製首先須要建立一個相應的egret或者eui對象,好比eui.Button、egret.TextField、egret.Bitmap等等,而後給對象設置相應屬性,好比label、x y座標,width, height等。 再使用main的addChild載入到畫布中(下面的this就是main對象,main繼承於eui.UILayer)。 demo中的代碼在載入loading的時候,使用了this.stage.addChild,直接addChild或者使用stage.addChild均可以載入到畫布中。 白鷺封裝的addEventListener方法和原生js的監聽方法是同樣的使用方法。 json
demo的代碼說到這裏總結一下,咱們在main入口對象中可使用addChild載入一個視圖對象到畫布中,好比文本,按鈕等。 咱們也能夠在main裏addChild一個視圖容器A,視圖容器A也能夠添加文本按鈕等,那咱們在視圖容器A中再次addChild視圖容器B,那麼這樣就造成了層級嵌套main->A->B,若是想象成dom元素就是div.main->div.A->div.B的關係,咱們用代碼來對比一下:canvas
class Main extends eui.UILayer { protected createChildren(): void { let A = new egret.DisplayObjectContainer(); this.addChild(A); let textA = new egret.TextField(); textA.text = 'text A Description'; A.addChild(textA); let B = new egret.DisplayObjectContainer(); A.addChild(B); let buttonB = new eui.Button(); buttonB.label = 'button B'; B.addChild(buttonB); } }
對應小程序
<div class="main"> <div class="A"> <span>text A Description</span> <div class="B"> <button value="button B"></button> </div> </div> </div>
根據以上代碼的理解和咱們要作的需求(實現一個回合制遊戲,這個遊戲也有不少頁面,首頁就包含不少按鈕和可能出現的彈窗,也有各類列表頁,還有最關鍵的戰鬥頁面)。 我在main裏寫一個initElement方法,建立基層容器,代碼以下圖,addChild默認根據前後順序肯定上下層關係,先載入的在下層。 首先最下層建立了一個背景層,接着是ScrollView和baseContent,頁面容器會載入到他們之中,若是頁面須要滾動會把頁面視圖對象載入到SV中,不須要滾動會載入到baseContent中,Layer和loading在更上層的位置。
基層容器準備好之後,咱們能夠建立一個首頁頁面。 我會建立3個文件:base.ts,Index_ui.ts,Index.ts。 Index繼承Index_ui,Index_ui繼承base。 全部的_ui都會繼承base,base會定義通用方法和屬性。 由於一個頁面到最後可能代碼量會比較大,甚至比較亂,因此才把一個頁面拆分紅page和page_ui,_ui裏寫視圖相關代碼,page裏調用_ui的方法、處理請求和編寫邏輯,達到視圖和邏輯分離的效果。 當首頁寫好之後,須要建立一個簡易路由,用路由提供的方法把Index添加到SV容器中。 我把路由直接寫到了main中,changePage就是頁面切換的方法,代碼大體以下:
經過remove和add視圖容器達到了切換頁面的效果。 下面說說編寫_ui頁面的規則,下面是Index_ui的部分代碼,el_layout提早把頁面元素的佈局信息提早定義並統一管理。 把Index邏輯頁面須要操做的元素引用到$el對象裏方便調用和操做。 把數據信息統一放在$data中。 建立頁面視圖元素以前,須要把第一個元素的y座標傳給 $firstEleY 這是爲了後面pageContentCenter方法能獲取到準確的頁面內容高度,pageContentCenter要執行在全部頁面元素建立完成以後,pageContentCenter會根據當前頁面的高度再匹配當前設備的高度進行垂直居中。
class Index_ui extends Base {
public el_layout = {
indexbg: {x:0, y:0, w:750, h:1665},
gold: {x:300, y:100, w:300, h:39}
};
public constructor() {
super();
this.RES_index = RES.getRes('index');
this.RES_common = RES.getRes('common');
}
public RES_index;
public RES_common;
public $el = {
gold: Object(egret.TextField)
}
public $data = {
gold: '0'
}
public async createView() {
//背景
let RES_bg = new egret.Bitmap( RES.getRes('indexbg') );
$util.setLayout(RES_bg, this.el_layout['indexbg']);
RES_bg.fillMode = egret.BitmapFillMode.REPEAT;
this.$main.PageBg.addChild(RES_bg);
//頂部元素必傳值
this.$firstEleY = this.el_layout.gold.y;
this.pageContentCenter(true);//根據內容計算處理居中
}
}
一個簡易的開發封裝的核心代碼已經搭建好了,然後咱們還須要封裝一些其它工具類,以下圖:配置文件($config)、封裝攔截器($api)、濾鏡($filter)、工具函數($util)、微信api封裝(Wx)。 Platform.ts是白鷺自動生成的文件,根據它的規則本身寫了一個Wx.ts文件,因爲不一樣平臺的接口形式各有不一樣,白鷺推薦開發者經過這種方式封裝平臺邏輯,以保證總體結構的穩定,白鷺推薦開發者將全部接口封裝爲基於 Promise 的異步形式。
和src同級的還有一個texture文件夾,裏面是TextureMeger使用精靈圖的相關文件,放在倉庫裏是方便後期管理。
簡易的初始化demo,我已經更新到github上https://github.com/zimv/egret-wechat-start。 egret-resource是源碼,egret-resource_wxgame是白鷺打包後的文件夾,它在開發者工具裏運行。 egret-resource_wxgame應該在ignore裏忽略,這裏沒有忽略是方便下載源碼的朋友直接在開發者工具裏運行demo。 當前程序使用白鷺引擎版本5.2.5。
demo裏隨便寫了幾個頁面,看下效果:
還有踩過不少坑,下面記錄一下:
當這一切都準備好之後,剩下的就是體力活啦,固然還有遊戲最重要的核心玩法實現、動畫和交互效果,這些多是一個遊戲實現難度最大的部分。倉庫地址:https://github.com/zimv/egret-wechat-start 。