import { sp } from "cc"; import GFSMBase, { GFSMProcessEnum, GFSMProcessInfo, GFSMProcessMode } from "./GFSMBase"; import GObject from "../GObject"; //角色动画名称枚举 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:{event:string,fun:Function}[] = []; starts:{name:string,fun:Function}[] = []; constructor(spine:sp.Skeleton,trackIndex:number = 0){ super(); this.spine = spine; this.trackIndex = trackIndex; //设置监听 this.spine.setEventListener(this.onEventListener.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){ this.events.push({ event, fun, }) } //监听动画开始播放 addStartListener(name:string,fun:Function){ this.starts.push({ name, fun, }) } onEventListener(entry: sp.spine.TrackEntry, ev: sp.spine.Event){ this.events.forEach(item => { if(item.event == ev.data.name){ item.fun(); } }); } onStartListener(entry: sp.spine.TrackEntry){ this.starts.forEach(item => { if(entry.animation.name == item.name){ item.fun(); } }); } // 流程图 process: { [key: number]: GFSMProcessAnimInfo; } = {} execute(process:GFSMProcessAnimInfo,dt:number){ process.ifTo = process.ifTo || []; process.to = process.to || []; process.mode = GFSMProcessMode.WaitExecute; process.execute = this.tick.bind(this); super.execute(process,dt); } //-1 继续播放 0 重新执行流程 * 指定分支 tick(dt:number,info:GFSMProcessAnimInfo){ //判断是否会切换动画 (默认不切换) 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(`播放动画-${this.spine.getComponent(GObject).nId}-`,info); info.track = this.spine.setAnimation(this.trackIndex,info.animName,!!info.isLoop); } return to; } }