前言
今天關於場景中特效MovieClip和UI上的不同之處思考嘗試了一些。場景中的MovieClip需要考慮多個方向,以及掛載點,且大多是通過配置來創建的,相比UI上公告板式樣規則處理要複雜,所以把UI上的序列幀單獨拆開,結合EXML編輯實現。
官方提供的MovieClip無法在EgretWing中所見即所得,於是…
第一種 通過MovieClipDataFactory創建
包 egret
類 public class MovieClip
繼承 egret.MovieClip Inheritance egret.DisplayObjectInheritance egret.EventDispatcherInheritance egret.HashObject
影片剪輯,可以通過影片剪輯播放序列幀動畫。MovieClip 類從以下類繼承而來:DisplayObject 和 EventDispatcher。不同於 DisplayObject 對象,MovieClip 對象擁有一個時間軸。
官方提供示例如下
MovieClip序列幀動畫-egret.MovieClip
幀動畫演示http://developer.egret.com/cn/example/egret2d/index.html#100-anim-flash
優點
- 美術使用
TextureMerger
編輯。提供mc的json配置和圖集。 - 支持單幀圖片的偏移(雖然這個工具真的。。但這個功能還是有的)
- 支持添加事件
- 支持swf,gif作爲源文件
缺點
- 無法在EgretWing中預覽(這個很苦惱)
- TextureMerger使用太酸爽(誰用誰知道,我們的美術被折磨的不輕)
示例代碼如下:
/**
* 以下示例演示了 MovieClip 序列幀動畫的使用。
* 該示例中假設資源已經用RES模塊加載完成
*/
class MovieClipExample extends egret.DisplayObjectContainer {
private data:any;
private texture:egret.Texture;
public constructor() {
super();
var loader:egret.HttpRequest = new egret.HttpRequest();
loader.responseType = egret.HttpResponseType.TEXT;
loader.addEventListener(egret.Event.COMPLETE, this.onLoadJsonComplete, this);
loader.open("resource/assets/chunli.json", egret.HttpMethod.GET);
loader.send();
}
private onLoadJsonComplete(event:egret.Event):void {
var loader:egret.HttpRequest = <egret.HttpRequest>event.target;
this.data = JSON.parse(loader.response);
var imageLoader:egret.ImageLoader = new egret.ImageLoader();
imageLoader.addEventListener(egret.Event.COMPLETE, this.onLoadTextureComplete, this);
imageLoader.load("resource/assets/chunli.png");
}
private onLoadTextureComplete(event:egret.Event):void {
var loader:egret.ImageLoader = <egret.ImageLoader>event.target;
//獲取加載到的紋理對象
var bitmapData:egret.BitmapData = loader.data;
//創建紋理對象
this.texture = new egret.Texture();
this.texture.bitmapData = bitmapData;
this.createMovieClip();
}
private createMovieClip():void {
//創建動畫工廠
var mcDataFactory:egret.MovieClipDataFactory = new egret.MovieClipDataFactory(this.data, this.texture);
//創建 MovieClip,將工廠生成的 MovieClipData 傳入參數
var mc:egret.MovieClip = new egret.MovieClip(mcDataFactory.generateMovieClipData("test"));
this.addChild(mc);
//添加播放完成事件
mc.addEventListener(egret.Event.COMPLETE, function (){
egret.log("COMPLETE");
}, this);
//添加循環播放完成事件
mc.addEventListener(egret.Event.LOOP_COMPLETE, function (){
egret.log("LOOP_COMPLETE");
}, this);
//播放攻擊動畫
mc.gotoAndPlay("attack", -1);
}
}
在此基礎上,可以對操作進行封裝,實現MovieClipManager,略過不說了。
第二種
不導出MovieClip,使用TextureMerger導出sheet格式。在EXML裏面放入一張圖片,使用該圖集的第一幀作爲source。邏輯中實現一個FrameAnimation類。
代碼中使用:
let frameAnimation = new FrameAnimation(this.image_xx, "mc_001");
傳入佔位Image組件和序列幀名,通過Update(dt)或者使用Timer計時計算應該切換到的圖片名稱。
優點
- EgretWing裏面可以預覽到動畫位置
- EgretWing裏面可以直接把適配設置好
- 邏輯調用簡單
- 只有圖集json,相比Mc格式的json資源小
缺點
- 不能加事件
- 看到EXML上的單個Image組件可能並不清楚這裏是個特效佔位符
- 需要對應的配置表來確定幀率,子圖片下標等
第三種
實現一個通用組件UIComponent_MovieClip。
使用:
- 固定特效:
擺到EXML上,填好source,如Eui_001.1
,可以自動播放。 - 動態加載特效: 擺到EXML上,留空source,如``,程序動態設置如:
this.uicomponent_mc_task.initMc("Eui_001");
/**
* UI序列幀特效
*/
class UIComponent_MovieClip extends eui.Image implements eui.UIComponent{
protected childrenCreated(): void {
super.childrenCreated();
let effectName = getDefaultEffectName(this.source);
if(effectName != ""){
this.initEffect(effectName);
}
}
/**
* 初始化特效
* @paramp_effectId cfg_effect中id 如Eui_52
*/
public initEffect(p_effectId: string) {
let config = GetConfig(p_effectId);
if(config == null) {
return;
}
···
this.addEventListener(egret.Event.ENTER_FRAME, this.onEnterFrame, this);
}
private onEnterFrame() {
···
if(this.mIndex == -1|| this.mIndex > this.endIndex) {
this.mIndex = this.startIndex;
}
this.source = this.imgPath + "_json."+ this.mIndex
this.mIndex++;
}
}
優點
- EgretWing可以預覽動畫位置大小
- EgretWing可以直接把適配設置好
- 不需要動態加載的固定特效可以不添加代碼
- 只有圖集json,相比Mc格式的json資源小
- 程序看到其他設計人員提交的EXML上該組件就清楚這裏是一個特效,如有設置source不處理,無則確認需求動態加載
缺點
- 需要對應的配置表來確定幀率,子圖片下標等
其他
- 自定義事件也可以統一配置在配置表裏面
後記
- 吐槽一下,工具真的是無力,TextureMerger不支持實時刷新,MovieClip編輯也是極其反人類。。Egret前路漫漫啊。。