居然使用 TyptScript...
先貼手冊地址:http://www.typescriptlang.org/docs/tutorial.html。
先要接受一個詭異的寫法:
private loadingView:LoadingUI;
- 首先支持了 private、public
- 類的對象名在前:loadingView
- 類的類型名在后:LoadingUI(在JS上封裝出了強類型?)
TyptScript 的特性:
- 類 Classes
- 接口 Interfaces
- 模塊 Modules
- 類型注解 Type annotations
- 編譯時類型檢查 Compile time type checking
- Arrow 函數 (類似 C# 的 Lambda 表達式)
只能說微軟的人硬是要用 C# 的語法特性重新封裝一下 JS 讓自己更順手么 - -。
Module:
略微看了下 Modules 的作用,提供了 export 與 import 關鍵字,那就很明白了:模塊與模塊之間是不透明的,允許其他模塊使用的資源需要用 export 聲明,引用其他模塊資源時需要用 import 進口。
Function:
function 函數名:參數列表:返回值類型 { 函數內容 }
function add(x: number, y: number): number { return x + y; }
let myAdd = function(x: number, y: number): number { return x+y; };
開始 Egret 之旅:
先上 API 參考:http://edn.egret.com/cn/index.php/apidoc/egret243/。
第一個 demo - createGameScene():
private createGameScene():void { console.log("Runtime start."); this.stage.width = 480; this.stage.height = 960; var bg: egret.Shape = new egret.Shape(); // Shape 繪制塊狀區域 bg.graphics.beginFill(0x0000ff); bg.graphics.drawRect(0, 0, this.stage.width, this.stage.height); bg.graphics.endFill(); this.addChild(bg); // 刷新到屏幕 var tx: egret.TextField = new egret.TextField(); // TextField 控制文本塊 tx.text = "I'm Jack, I will use Egret create a fantasy mobile game!"; tx.x = 20; tx.y = 20; tx.width = this.stage.width - 40; this.addChild(tx); tx.touchEnabled = true; //激活 touch tx.addEventListener(egret.TouchEvent.TOUCH_TAP, this.touchHandler, this); //增加事件監聽 console.log("Runtime end."); }
private touchHandler(evt:egret.TouchEvent):void{ //事件處理API var tx:egret.TextField = evt.currentTarget; tx.textColor = 0x00ff00; }
資源配置:
Resoure 目錄下的 default.res.json 是資源清單文件,每一項資源都包含 name、type、url 三個屬性。
-
name:表示這個資源的唯一標識符。注意資源比較多的項目應確定一套命名規則,避免不同資源命名之間重復或太接近而易混淆。
-
type:表示資源類型。緊跟着會進一步講解其含義及取值規則。
-
url:表示當前資源文件的路徑。通常我們約定配置類型的資源置於config子目錄下;其他類型置於assets子目錄下。
-
每個”resource”單位中的type,是Egret約定好的若干類型,最常用的有以下類型:
-
image:表示各種常見的圖片類型,包括PNG和JPG格式,載入后將解析為egret.Texture對象;
-
text:表示文本類型,即文本文件,載入后將解析為string對象;
-
json:也是一種文本類型,不過內容是json格式的,載入后將直接解析為json對象;
-
-
我們在某種游戲場合,需要同時加載若干資源,用以准備后續的游戲流程顯示。我們可以將若干項資源定義為一個資源組。需要時,只需加載這個資源組即可。 “groups”是預加載資源組的配置,每項是一個資源組。 每一個資源組須包含兩個屬性:
-
name:表示資源組的組名
-
keys:表示這個資源組包含哪些資源,里面的逗號分隔的每一個字符串,都與”resource”下的資源name對應。
白鷺的這張圖還是具有代表性的:
資源加載:
非常簡單明了的邏輯:清單加載監聽 -- 加載清單 -- 關閉清單監聽 -- 開啟資源組加載監聽 -- 按需加載資源組 -- 加載完資源后關閉監聽。
RES.addEventListener(RES.ResourceEvent.CONFIG_COMPLETE, this.onConfigComplete, this); //加載配置清單事件監聽 RES.loadConfig("resource/default.res.json", "resource/"); //加載配置清單
private onConfigComplete(event:RES.ResourceEvent):void { //回調 -- 加載清單完成時 RES.removeEventListener(RES.ResourceEvent.CONFIG_COMPLETE, this.onConfigComplete, this); //移除加載清單監聽 RES.addEventListener(RES.ResourceEvent.GROUP_COMPLETE, this.onResourceLoadComplete, this); //資源組加成完成監聽 RES.addEventListener(RES.ResourceEvent.GROUP_LOAD_ERROR, this.onResourceLoadError, this); //資源組加載錯誤監聽 RES.addEventListener(RES.ResourceEvent.GROUP_PROGRESS, this.onResourceProgress, this); //資源組加載進度監聽 RES.addEventListener(RES.ResourceEvent.ITEM_LOAD_ERROR, this.onItemLoadError, this); RES.loadGroup("preload"); }
private onResourceLoadComplete(event:RES.ResourceEvent):void { //回調 -- 資源組加載完成時 if (event.groupName == "preload") { this.stage.removeChild(this.loadingView); //刪除進度條 RES.removeEventListener(RES.ResourceEvent.GROUP_COMPLETE, this.onResourceLoadComplete, this); //移除各類監聽 RES.removeEventListener(RES.ResourceEvent.GROUP_LOAD_ERROR, this.onResourceLoadError, this); RES.removeEventListener(RES.ResourceEvent.GROUP_PROGRESS, this.onResourceProgress, this); RES.removeEventListener(RES.ResourceEvent.ITEM_LOAD_ERROR, this.onItemLoadError, this); this.createGameScene(); } }
資源管理的統一入口是全局的 “RES” 命名空間里的 API。
Stage 可通過設置子項的“顯示優先級”來控制層次:
this.setChildIndex( captain, 2);
來做一個官網 超級英雄的例子:
1. 先把4個超級英雄P出來做成資源,放入 Resource 目錄的 asserts 文件夾下。
2. 配置 default.res.json,新增一個資源組。
3. 在 Main 中,將加載 preload 改成加載 heroes 資源組。
private createGameScene():void { var bg:egret.Shape = new egret.Shape(); bg.graphics.beginFill(0x336699); bg.graphics.drawRect(0, 0, this.stage.stageWidth, this.stage.stageHeight); bg.graphics.endFill(); this.addChild(bg); var batman:egret.Bitmap = new egret.Bitmap(RES.getRes("hero1_png")); batman.x = 10; batman.y = 20; this.addChild(batman); var captain:egret.Bitmap = new egret.Bitmap(RES.getRes("hero2_png")); captain.x = 130; captain.y = 20; this.addChild(captain); var superman:egret.Bitmap = new egret.Bitmap(RES.getRes("hero3_png")); superman.x = 250; superman.y = 20; this.addChild(superman); var hulk:egret.Bitmap = new egret.Bitmap(RES.getRes("hero4_png")); hulk.x = 370; hulk.y = 20; this.addChild(hulk); console.log("Display indexes:", this.getChildIndex(bg), this.getChildIndex(batman), this.getChildIndex(captain), this.getChildIndex(superman), this.getChildIndex(hulk)); this.swapChildren(superman, hulk); console.log("Display indexes:", this.getChildIndex(bg), this.getChildIndex(batman), this.getChildIndex(captain), this.getChildIndex(superman), this.getChildIndex(hulk)); hulk.anchorOffsetX = 30; //設置錨點 -- 將圖片上的某個點設置為原點,可用作為該圖標的代表將其部署在一個相對於畫布原點的坐標上 hulk.anchorOffsetY = 40; hulk.x += 30; //修正設置錨點帶來的偏移 hulk.y += 40; this.times = -1; var self = this; this.stage.addEventListener(egret.TouchEvent.TOUCH_TAP,() => { //蠻做了一個測試,可以用類似C#的匿名函數寫法,也可以用 function() 代替 () => switch(++self.times % 3){ case 0: egret.Tween.get(batman).to({x:superman.x}, 300, egret.Ease.circIn); //get:激活一個對象為其添加動畫,x:修改其橫坐標屬性 egret.Tween.get(superman).to({x:batman.x}, 300, egret.Ease.circIn); //to:修改其屬性 - para1:目標狀態,param2:持續時間,param3:補間方程 break; case 1: egret.Tween.get(captain).to({alpha:0.3}, 300, egret.Ease.circIn).to({alpha:1}, 300, egret.Ease.circIn); //alpha:修改其透明通道屬性 break; case 2: egret.Tween.get(hulk).to({scaleX:0.4, scaleY:0.4}, 500, egret.Ease.circIn).to({scale:1, scaleY:1}, 500, egret.Ease.circIn); //scaleX、scaleY:修改其縮放比例屬性 break; } }, this); }