import { sp } from "cc"; import GFSMBase, { GFSMProcessEnum, GFSMProcessInfo, GFSMProcessMode } from "./GFSMBase"; import GObject from "../GObject"; import { JNFrameInfo } from "../../../../../extensions/ngame/assets/ngame/sync/frame/JNSyncFrame"; //角色动画名称枚举 export enum GFSMBattleAminEnum { Wait = "std", //等待 Walk = "walk", //移动 Attack = "atk", //攻击 Fly = "jifei", //击飞 } //动画流程信息 export interface GFSMProcessAnimInfo extends GFSMProcessInfo{ //动画名称 animName:string; //是否循环播放 isLoop?:boolean; //与下一个动作的融合值 mixs?:number[]; //播放的轨道 track?:sp.spine.TrackEntry; //条件跳转 ifTo?:(() => boolean)[]; } //动画状态机基类 export abstract class GFSMAnimBase extends GFSMBase{ //轨道的索引 trackIndex:number; //动画Root spine:sp.Skeleton; events:{[key:string]:Function[]}= {}; starts:{[key:string]:Function[]}= {}; ends:{[key:string]:Function[]}= {}; constructor(spine:sp.Skeleton,trackIndex:number = 0){ super(); this.spine = spine; this.trackIndex = trackIndex; //设置监听 this.spine.setEventListener(this.onEventListener.bind(this)); //设置结束监听 this.spine.setCompleteListener(this.onEndListener.bind(this)); // //因为SpineBUG所以不使用Spine监听 采用自己调用 // this.spine.setStartListener(this.onStartListener.bind(this)); } open(){ super.open(); //重置 Object.values(this.process).forEach(info => { info.track = null; }) } //添加事件监听 addEventListener(event:string,fun:Function){ if(!this.events[event]) this.events[event] = []; this.events[event].push(fun); } //监听动画开始播放 addStartListener(name:string,fun:Function){ if(!this.starts[name]) this.starts[name] = []; this.starts[name].push(fun); } //监听动画结束播放 addEndListener(name:string,fun:Function){ if(!this.ends[name]) this.ends[name] = []; this.ends[name].push(fun); } //删除事件监听 delEventListener(event:string,fun:Function){ if(!this.events[event]) this.events[event] = []; let index = this.events[event].indexOf(fun); if(index >= 0) this.events[event].splice(index,1) } //删除动画开始播放 delStartListener(name:string,fun:Function){ if(!this.starts[name]) this.starts[name] = []; let index = this.starts[name].indexOf(fun); if(index >= 0) this.starts[name].splice(index,1) } //删除动画结束播放 delEndListener(name:string,fun:Function){ if(!this.ends[name]) this.ends[name] = []; let index = this.ends[name].indexOf(fun); if(index >= 0) this.ends[name].splice(index,1) } onEventListener(entry: sp.spine.TrackEntry, ev: sp.spine.Event){ if(!this.events[ev.data.name]) this.events[ev.data.name] = []; this.events[ev.data.name].forEach(fun => { fun(); }); } onStartListener(entry: sp.spine.TrackEntry){ if(!this.starts[entry.animation.name]) this.starts[entry.animation.name] = []; this.starts[entry.animation.name].forEach(fun => { fun(); }); } onEndListener(entry: sp.spine.TrackEntry){ if(!this.ends[entry.animation.name]) this.ends[entry.animation.name] = []; this.ends[entry.animation.name].forEach(fun => { fun(); }); } // 流程图 process: { [key: number]: GFSMProcessAnimInfo; } = {} execute(process:GFSMProcessAnimInfo,dt:number,frame:JNFrameInfo){ process.ifTo = process.ifTo || []; process.to = process.to || []; process.mode = GFSMProcessMode.WaitExecute; process.execute = this.tick.bind(this); super.execute(process,dt,frame); } //-1 继续播放 0 重新执行流程 * 指定分支 tick(dt:number,info:GFSMProcessAnimInfo,frame:JNFrameInfo){ //判断是否会切换动画 (默认不切换) let to = GFSMProcessEnum.Wait; info.ifTo.forEach((run,index) => { if(run()){ to = info.to[index]; } }); if(to >= 0) { //和下一个动作融合 let mix = info.mixs[to - 1] || 0; if(mix){ //设置融合 this.spine.setMix(info.animName,this.process[to].animName,mix); } info.track = null; return to; } //播放动画 if(!info.track){ console.log(`${frame.index} 播放动画-${this.spine.getComponent(GObject).nId}-`,info); info.track = this.spine.setAnimation(this.trackIndex,info.animName,!!info.isLoop); this.onStartListener(info.track); } return to; } }