/* 文件名:AnimationClass.nut 路径:Core/BaseClass/AnimationClass/AnimationClass.nut 创建日期:2024-05-07 23:25 文件用途:动画类 */ class Animation extends CL_SpriteObject { //Ani是否可用 IsUsability = true; //当前帧数 CurrentFrameIndex = 0; //总帧数 TotalFrameIndex = 0; //当前帧时间 CurrentIndexT = 0; //当前帧 CurrentFrame = null; //下帧延迟 NextFrameDelay = 9999999; //染色Flag DyeingFlag = false; //插值模式 InterpolationFlag = null; //状态机对象(只有存在时才有KeyFlag) StateMachine = null; //Ani的标签 AnimationFlag = null; //帧对象数组 FrameArr = null; //图片精灵帧对象 SpriteArr = null; //Ani类型 Type = "normal"; //Ani路径 AniPath = null; //是否描边 IsOutline = false; //描边颜色 OutlineColor = null; //描边对象List OutlineList = null; //当前描边对象 CurrentOutline = null; //染色颜色 DyeColor = null; //染色帧List DyeFrameList = null; //整体染色 DyeAllFlag = false; //裁切数据 CropRect = null; //附加选项 AdditionalOptions = null; function _typeof() { return "animation"; } constructor(...) { base.constructor(); //精灵帧数组 SpriteArr = []; //帧数组 FrameArr = []; //描边对象List OutlineList = []; //判断是否有特殊处理 if (vargv.len() > 1) { AdditionalOptions = vargv[1]; } //初始化数据 InitData(vargv[0]); } function InitData(Data) { local Buf; if (type(Data) == "table") { Buf = Data; } //从PVF数据加载 else if (type(Data) == "string") { Data = String.RegRealPath(Data); Buf = sq_DeepCopy(ScriptData.GetAni(Data)); //还需要判断一下有没有als local AlsBuf = ScriptData.GetFile(Data + ".als"); if (AlsBuf) { local m_data = ScriptData.GetFileData(Data + ".als", function(DataTable, Data) { local Anilist = {}; while (!Data.Eof()) { local Pack = Data.Get(); if (Pack == "[use animation]") { local AniPath = Data.Get(); local AniKey = Data.Get(); if (!(AniKey in Anilist)) Anilist[AniKey] <- {}; Anilist[AniKey].path <- AniPath; } else if (Pack == "[none effect add]") { local AniLayer = [Data.Get(), Data.Get()]; local AniKey = Data.Get(); if (!(AniKey in Anilist)) Anilist[AniKey] <- {}; Anilist[AniKey].layer <- AniLayer; } else if (Pack == "[add]") { local AniLayer = [Data.Get(), Data.Get()]; local AniKey = Data.Get(); if (!(AniKey in Anilist)) Anilist[AniKey] <- {}; Anilist[AniKey].layer <- AniLayer; } } DataTable.Anilist <- Anilist; DataTable.dirpath <- DataTable.filepath.slice(0, DataTable.filepath.lastfind("/") + 1); }); foreach(Index, Info in m_data.Anilist) { local anibuf = Animation(m_data.dirpath + Info.path.tolower()); anibuf.SetZOrder(Info.layer[1]); Addchild(anibuf); } } } if (Buf) { AniPath = Buf.filepath; AnimationFlag = Buf.Flag; FrameArr = Buf.Frame; foreach(FrameObj in FrameArr) { local SpriteFramebuf; //img路径判空 if (FrameObj.Img_Path) { //如果有附加处理 格式化 if (AdditionalOptions && AdditionalOptions.rawin("ImgFormat")) FrameObj.Img_Path = AdditionalOptions["ImgFormat"](FrameObj.Img_Path); SpriteFramebuf = CL_SpriteFrameObject("sprite/" + FrameObj.Img_Path, FrameObj.Img_Index); //坐标 SpriteFramebuf.SetPosition(FrameObj.Pos); } else { SpriteFramebuf = CL_SpriteFrameObject("sprite/interface/base.img", 0); } SpriteArr.append(SpriteFramebuf); } } else { error("创建Ani失败,找不到Ani数据"); } //初始化完毕 如果是第一次初始化 而非重新构造 设置大小为第0帧大小否则天空 地板等依靠大小的初始化会有问题 if (CurrentIndexT == 0) SetSize(SpriteArr[0].GetSize()); //记录总帧数 TotalFrameIndex = FrameArr.len(); DyeFrameList = array(TotalFrameIndex); } //被添加时 要刷新一下当前帧 function OnAddchild(Parent) { base.OnAddchild(Parent); FlushFrame(0); } //重置Ani function Reset() { IsUsability = true; FlushFrame(0); } //赋予状态机 function BindenvStateMachine(gM) { StateMachine = gM; } //获取当前帧信息 function GetCurrentFrameInfo() { return FrameArr[CurrentFrameIndex]; } //设置描边 function SetOutline(Flag, Color = 0xffffffff) { IsOutline = Flag; //如果是开启 if (Flag) { //如果没有创建过描边对象就创建 if (OutlineList.len() == 0) { foreach(FrameSf in SpriteArr) { local OutlineCanvasObj = FrameSf.CreateOutLine(Color); // OutlineCanvasObj.SetZOrder(-1); // OutlineCanvasObj.SetPosition(-1, -1); // OutlineCanvasObj.SetPosition(-FrameSf.GetSize().w / 2, -FrameSf.GetSize().h); OutlineList.push(OutlineCanvasObj); } } //先把当前帧的描边对象设置上 AddOutlineChild(); } else { //移除当前描边对象 if (CurrentOutline) { Removechild(CurrentOutline); } } } //设置整体染色 function SetDye(Color, Flag = 0) { foreach(Index, FrameSf in SpriteArr) { local DyeFrame = FrameSf.Dye(Color, Flag); DyeFrameList[Index] = (DyeFrame); } DyeColor = Color; DyeAllFlag = true; } //设置裁切 function SetCropRect(Parameter1, Parameter2, ...) { if (vargv.len() == 0) { local Point1 = Parameter1; local Point2 = Parameter2; CropRect = [Point1.x, Point1.y, Point2.x, Point2.y]; } else if (vargv.len() == 2) { local X1 = Parameter1; local Y1 = Parameter2; local X2 = vargv[0]; local Y2 = vargv[1]; CropRect = [X1, Y1, X2, Y2]; } } //添加描边子对象 function AddOutlineChild() { //如果有上一个描边对象先移除 if (CurrentOutline) { Removechild(CurrentOutline); } //如果没有添加为子对象则添加 local OutlineCanvasObj = OutlineList[CurrentFrameIndex]; if (OutlineCanvasObj.Parent == null) { CurrentOutline = OutlineCanvasObj; Addchild(CurrentOutline); } } function FlushFrame(Index) { //同步当前帧 CurrentFrameIndex = Index; //当前帧更换为本帧 CurrentFrame = SpriteArr[CurrentFrameIndex]; //如果是整体染色 则直接使用染色帧 if (DyeAllFlag) CurrentFrame = DyeFrameList[CurrentFrameIndex]; CurrentFrame.SetPosition(FrameArr[CurrentFrameIndex].Pos); SetFrame(CurrentFrame); local FrameInfo = FrameArr[CurrentFrameIndex]; local FlagBuf = FrameInfo.Flag; NextFrameDelay = FrameInfo.Delay; //关键帧 if ("SET_FLAG" in FlagBuf) { if (StateMachine && StateMachine.State != -1) StateMachine.ChangeAniKeyFlag(FlagBuf.SET_FLAG); } //播放音效 if ("PLAY_SOUND" in FlagBuf) { Sq_PlaySoundEffect(FlagBuf.PLAY_SOUND); } //缩放 if ("IMAGE_RATE" in FlagBuf) { SetScale(FlagBuf.IMAGE_RATE.x, FlagBuf.IMAGE_RATE.y); } //线性减淡 if ("GRAPHIC_EFFECT_LINEARDODGE" in FlagBuf) { SetMode(0); } //旋转 if ("IMAGE_ROTATE" in FlagBuf) { SetRotation(FlagBuf.IMAGE_ROTATE); } //染色 在没有开启整体染色时才执行的逻辑 if (!DyeAllFlag) { if ("RGBA" in FlagBuf) { DyeingFlag = true; if (!DyeFrameList[CurrentFrameIndex]) { local RGBA_V = sq_RGBA(FlagBuf.RGBA[0], FlagBuf.RGBA[1], FlagBuf.RGBA[2], FlagBuf.RGBA[3]); DyeFrameList[CurrentFrameIndex] = SpriteArr[CurrentFrameIndex].Dye(RGBA_V); DyeFrameList[CurrentFrameIndex].SetPosition(FrameArr[CurrentFrameIndex].Pos); } CurrentFrame = DyeFrameList[CurrentFrameIndex]; SetFrame(CurrentFrame); //设置透明度 SetOpacity(FlagBuf.RGBA[3].tofloat() / 250.0); } else { if (DyeingFlag) { DyeingFlag = false; //恢复透明度 SetOpacity(1.0); } } } //插值模式 if ("INTERPOLATION" in FlagBuf) { //初始化插值数据 if (!InterpolationFlag) { InterpolationFlag = []; //旧插值数据 InterpolationFlag.push(sq_DeepCopy(FrameArr[CurrentFrameIndex])); //新插值数据 InterpolationFlag.push(sq_DeepCopy(FrameArr[CurrentFrameIndex + 1])); } } else { if (InterpolationFlag) { InterpolationFlag = null; } } //如果有描边 if (IsOutline) AddOutlineChild(); //Ani对象的大小同步为精灵帧对象的大小 if (CurrentFrame) SetSize(CurrentFrame.GetSize()); //裁切 if (CropRect) { base.SetCropRect(CropRect[0], CropRect[1], CropRect[2], CropRect[3]); //所有子对象裁切 foreach(Child in Children) { Child.SetCropRect(CropRect[0], CropRect[1], CropRect[2], CropRect[3]); } } } function InterpolationLogic() { if (!InterpolationFlag) return; //插值倍率 local InterRate = Math.getUniformVelocity(0, 100, CurrentIndexT, NextFrameDelay).tofloat() / 100.0; //旧插值数据 local OldData = InterpolationFlag[0]; //新插值数据 local NewData = InterpolationFlag[1]; //RGBA插值 { local OldRgbaData = [255, 255, 255, 250]; local NewRgbaData = [255, 255, 255, 250]; if ("RGBA" in OldData.Flag) OldRgbaData = OldData.Flag.RGBA; if ("RGBA" in NewData.Flag) NewRgbaData = NewData.Flag.RGBA; local RgbaData = [ OldRgbaData[0] + (NewRgbaData[0] - OldRgbaData[0]) * InterRate, OldRgbaData[1] + (NewRgbaData[1] - OldRgbaData[1]) * InterRate, OldRgbaData[2] + (NewRgbaData[2] - OldRgbaData[2]) * InterRate, OldRgbaData[3] + (NewRgbaData[3] - OldRgbaData[3]) * InterRate ]; // //设置染色 // DyeFrameList[CurrentFrameIndex] = CurrentFrame.Dye(sq_RGBA(RgbaData[0], RgbaData[1], RgbaData[2], RgbaData[3])); // CurrentFrame = DyeFrameList[CurrentFrameIndex]; // CurrentFrame.SetPosition(FrameArr[CurrentFrameIndex].Pos); // SetFrame(CurrentFrame); //设置透明度 SetOpacity(RgbaData[3].tofloat() / 250.0); }; //坐标 { local PosData = { x = OldData.Pos.x + (NewData.Pos.x - OldData.Pos.x) * InterRate, y = OldData.Pos.y + (NewData.Pos.y - OldData.Pos.y) * InterRate } CurrentFrame.SetPosition(PosData); SetFrame(CurrentFrame); }; //缩放 { local OldRateData = { x = 1.0, y = 1.0 }; local NewRateData = { x = 1.0, y = 1.0 }; if ("IMAGE_RATE" in OldData.Flag) OldRateData = OldData.Flag.IMAGE_RATE; if ("IMAGE_RATE" in NewData.Flag) NewRateData = NewData.Flag.IMAGE_RATE; local ScaleData = { x = OldRateData.x + (NewRateData.x - OldRateData.x) * InterRate, y = OldRateData.y + (NewRateData.y - OldRateData.y) * InterRate } SetScale(ScaleData); } //旋转 { local OldRotateData = 0.0; local NewRotateData = 0.0; if ("IMAGE_ROTATE" in OldData.Flag) OldRotateData = OldData.Flag.IMAGE_ROTATE; if ("IMAGE_ROTATE" in NewData.Flag) NewRotateData = NewData.Flag.IMAGE_ROTATE; local RotateData = OldRotateData + (NewRotateData - OldRotateData) * InterRate; SetRotation(RotateData); } } //override function OnUpdate(dt) { //可用性检查 if (IsUsability) { //累加当前帧时间 CurrentIndexT += dt; //插值模式判断 InterpolationLogic(); //当前帧时间 超过 当前帧延迟就需要切换帧了 if (CurrentIndexT >= NextFrameDelay) { CurrentIndexT = 0; //如果当前帧小于总帧数就切换 if (CurrentFrameIndex<(TotalFrameIndex - 1)) { FlushFrame(CurrentFrameIndex + 1); } //说明播放完毕了 else { //如果有循环 if ("LOOP" in AnimationFlag) { FlushFrame(0); } //没有循环触发状态机回调 else { //将不再可用 IsUsability = false; if (StateMachine && StateMachine.State != -1) StateMachine.ChangeAniEndFlag(); } } } } //Animation类下只会有精灵 因此不需要对子对象进行更新 还有可能有als 还得想办法优化 base.OnUpdate(dt); } }