437 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
			
		
		
	
	
			437 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
| /*
 | |
| 文件名: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);
 | |
|     }
 | |
| } |