/* 文件名:Animation_Class.nut 路径:Base/_Tool/Animation_Class.nut 创建日期:2024-10-21 16:57 文件用途:动画类 */ class Rindro_Animation { //Ani是否可用 IsUsability = true; //当前帧数 CurrentFrameIndex = 0; //当前帧时间 CurrentIndexT = 0; //当前帧 CurrentFrame = null; //Ani的标签 AnimationFlag = null; //图片对象数组 PngList = null; //帧对象数组 FrameList = null; //附加选项 AdditionalOptions = null; //角度 Angle = 0; constructor(Data, ...) { PngList = []; FrameList = []; //附加选项 if (vargc > 0) AdditionalOptions = vargv[0]; //初始化数据 InitData(Data); } function InitData(Data) { local Buf; if (type(Data) == "table") { Buf = Data; } //从PVF数据加载 else if (type(Data) == "string") { local ReadObject = R_Utils.GetScriptFileReader(Data); if (ReadObject) { Buf = Rindro_Script.ReadAnimation(ReadObject); } } if (Buf) { AnimationFlag = Buf.Flag; FrameList = Buf.Frame; foreach(FrameObj in FrameList) { //如果有附加处理 格式化 if (AdditionalOptions && AdditionalOptions.rawin("ImgFormat")) FrameObj.Img_Path = AdditionalOptions["ImgFormat"](FrameObj.Img_Path); local Png = Rindro_Image.Load(FrameObj.Img_Path); // Png.Draw(-500, -500); //如果有附加处理 坐标 if (AdditionalOptions && AdditionalOptions.rawin("Pos")) { FrameObj.Pos.x += AdditionalOptions["Pos"].x; FrameObj.Pos.y += AdditionalOptions["Pos"].y; } // Spritebuf.SetPosition(FrameObj.Pos); PngList.append(Png); } } else { AnimationFlag = {}; FrameList.append({ AttackBox = [], DamageBox = [], Delay = 800, Flag = {}, Img_Index = 0, Img_Path = "", Pos = { x = -248, y = -331 } }) // print(Data); // print("创建Ani失败,找不到Ani数据"); } } //重置Ani function Reset() { IsUsability = true; FlushFrame(0); } //获取当前帧信息 function GetCurrentFrameInfo() { return FrameList[CurrentFrameIndex]; } function FlushFrame(Index) { if (PngList.len() <= 0) return; //同步当前帧 CurrentFrameIndex = Index; //当前帧更换为本帧 CurrentFrame = PngList[CurrentFrameIndex]; local FlagBuf = FrameList[CurrentFrameIndex].Flag; //关键帧 if ("SET_FLAG" in FlagBuf) { // if (StateMachine && StateMachine.State != -1) StateMachine.ChangeAniKeyFlag(FlagBuf.SET_FLAG); } //播放音效 if ("PLAY_SOUND" in FlagBuf) { R_Utils.PlaySound(FlagBuf.PLAY_SOUND); } } //绘制 function DrawFrame(X, Y) { // local NowDrawPng = CurrentFrame; if (FrameList.len() <= 0) return; local FrameObj = FrameList[CurrentFrameIndex]; // printT(FrameObj); //坐标偏移 local XOffset = FrameObj.Pos.x; local YOffset = FrameObj.Pos.y; //染色 local RGBA = sq_RGBA(255, 255, 255, 255); if ("RGBA" in FrameObj.Flag) { local Fbuf = FrameObj.Flag.RGBA; RGBA = sq_RGBA(Fbuf[0].tointeger(), Fbuf[1].tointeger(), Fbuf[2].tointeger(), Fbuf[3].tointeger()); } //缩放 local XRate = 1.0; local YRate = 1.0; if ("IMAGE_RATE" in FrameObj.Flag) { local Fbuf = FrameObj.Flag.IMAGE_RATE; XRate = Fbuf.x; YRate = Fbuf.y; } //线性减淡 if ("GRAPHIC_EFFECT_LINEARDODGE" in FrameObj.Flag) { L_sq_SetDrawImgModel(2, 0); } if (CurrentFrame) CurrentFrame.DrawExPng(FrameObj.Img_Index, X + XOffset, Y + YOffset, Angle, RGBA, XRate, YRate); //线性减淡 if ("GRAPHIC_EFFECT_LINEARDODGE" in FrameObj.Flag) { L_sq_ReleaseDrawImgModel(); } } function Draw(X, Y) { //可用性检查 if (IsUsability) { DrawFrame(X, Y); //累加当前帧时间 CurrentIndexT += Rindro_Duration; //当前帧时间 超过 当前帧延迟就需要切换帧了 if ("Delay" in FrameList[CurrentFrameIndex] && CurrentIndexT >= FrameList[CurrentFrameIndex].Delay) { CurrentIndexT = 0; //如果当前帧小于总帧数就切换 if (CurrentFrameIndex<(FrameList.len() - 1)) { FlushFrame(CurrentFrameIndex + 1); } //说明播放完毕了 else { //如果有循环 if ("LOOP" in AnimationFlag) { FlushFrame(0); } //没有循环触发状态机回调 else { //将不再可用 IsUsability = false; } } } } } function DrawIndex(X, Y, Index) { // return; if (IsUsability) { FlushFrame(Index); DrawFrame(X, Y); } } } //绘制角色类 class Rindro_Draw_Character { //名字 Name = null; //职业 Job = null; //绘制体信息 DrawInfo = null; //隐藏图层Map HideMap = null; ENUM_RINDRO_JOB_NAME = ["swordman", "fighter", "gunner", "mage", "priest", "atgunner", "thief", "atfighter", "atmage", "demonicswordman", "creatormage"]; ENUM_RINDRO_JOB_TITLE_HEIGHT = [ //男鬼剑士 { x = -42, y = -154 }, //女格斗 { x = -42, y = -140 }, //男神枪手 { x = -44, y = -168 }, //女魔法师 { x = -46, y = -126 }, //男圣职者 { x = -46, y = -166 }, //女神枪手 { x = -42, y = -156 }, //女暗夜使者 { x = -44, y = -154 }, //男格斗家 { x = -45, y = -160 }, //男魔法师 { x = -45, y = -140 }, //黑暗武士 { x = -42, y = -154 }, //缔造者 { x = -46, y = -126 }, ]; ENUM_RINDRO_JOB_FACE_HEIGHT = [ //男鬼剑士 { x = 11, y = 111 }, //女格斗 { x = 9, y = 103 }, //男神枪手 { x = 13, y = 131 }, //女魔法师 { x = 14, y = 87 }, //男圣职者 { x = 16, y = 126 }, //女神枪手 { x = 11, y = 119 }, //女暗夜使者 { x = 12, y = 115 }, //男格斗家 { x = 13, y = 119 }, //男魔法师 { x = 13, y = 101 }, //黑暗武士 { x = -42, y = -154 }, //缔造者 { x = -46, y = -126 }, ]; //获取角色AniBy装备 function GetCharacAniByEqu(Job, Equ, AniName) { local AniList = []; foreach(value in Equ) { if (value > 0) { local ListBuf = CreateEquipmentAni(value, Job, AniName); AniList.extend(ListBuf); } } local n = AniList.len(); for (local i = 0; i< n - 1; i++) { for (local j = i + 1; j< n; j++) { if (AniList[i].Layer > AniList[j].Layer) { // 交换两个元素 local temp = AniList[i]; AniList[i] = AniList[j]; AniList[j] = temp; } } } return AniList; } function CreateEquipmentAni(Index, Job, AniName) { local AniList = []; //获取装备或时装的文件路径 local FilePath = R_Utils.GetEquPath(Index); if (FilePath) { local ReadObject = R_Utils.GetScriptFileReader("equipment/" + FilePath); if (ReadObject) { local Equ = Rindro_Script.ReadEquipment(ReadObject); //职业名字 local JobName = ENUM_RINDRO_JOB_NAME[Job]; //没有装备类型 if (!(Equ.rawin("equipment_type"))) Equ.equipment_type <- "normal"; //光环单独处理 其他的在下面处理 if (Equ.equipment_type == "aurora avatar") { foreach(Path in Equ.Aurora.Back) { local AniBuf = Rindro_Animation(Path); AniList.append({ Ani = AniBuf, Layer = -10000, }); } foreach(Path in Equ.Aurora.Front) { local AniBuf = Rindro_Animation(Path); AniList.append({ Ani = AniBuf, Layer = 10000, }); } } //称号 else if (Equ.equipment_type == "title name") { local PathBuf = "equipment/" + FilePath; PathBuf = PathBuf.slice(0, R_Utils.String.FindLastSubstring(PathBuf, "/")); local Path = PathBuf + "/" + Equ.custom_animation; local Ao = { Pos = ENUM_RINDRO_JOB_TITLE_HEIGHT[Job] } local AniBuf = Rindro_Animation(Path, Ao); AniList.append({ Ani = AniBuf, Layer = 10001, }); } //没有Ani 就那种透明时装 if (!(Equ.rawin("Ani_" + JobName))) return AniList; //记录时装的隐藏图层值 if (Equ.rawin("hidelayer")) { foreach(value in Equ["hidelayer"]) { HideMap.rawset(value, true); } } //读取Ani配置 local AniScript = Equ["Ani_" + JobName]; // printT(AniScript); if (Equ.equipment_type == "skin avatar") { local Path; if (JobName.find("at") >= 0) { Path = format("character/%s/atanimation/%s", JobName.slice(2), AniName); } else Path = format("character/%s/animation/%s", JobName, AniName); local Ao = { ImgVariation = AniScript.variation, ImgFormat = function(ImgPath) { if (ImgVariation[0] > 0) { local Pos = ImgPath.find("%04d"); ImgPath = ImgPath.slice(0, Pos) + "%02d%02d" + ImgPath.slice(Pos + 4); return format(ImgPath, ImgVariation[0], ImgVariation[1]); } else { return format(ImgPath, ImgVariation[1]); } } } local AniBuf = Rindro_Animation(Path, Ao); AniList.append({ Ani = AniBuf, Layer = -1, }); } else { foreach(Info in AniScript.layer_variation) { local PathBuf = "equipment/" + FilePath; PathBuf = PathBuf.slice(0, R_Utils.String.FindLastSubstring(PathBuf, "/")); local Path = PathBuf + "/" + Info.Path + "/" + AniName; local Ao = { ImgVariation = AniScript.variation, ImgFormat = function(ImgPath) { return format(ImgPath, ImgVariation[0], ImgVariation[1]); } } local AniBuf = Rindro_Animation(Path, Ao); AniList.append({ Ani = AniBuf, Layer = Info.Zorder, }); } } } } return AniList; } constructor(Job, EquipmentArr, Action, Name) { HideMap = {}; DrawInfo = GetCharacAniByEqu(Job, EquipmentArr, Action); this.Job = Job; this.Name = Name; } function Draw(X, Y) { foreach(AniInfo in DrawInfo) { // print(AniInfo.Layer); if (!HideMap.rawin(AniInfo.Layer)) AniInfo.Ani.Draw(X, Y); } if (Name) { L_sq_DrawCode(Name, 44 + X + ENUM_RINDRO_JOB_TITLE_HEIGHT[Job].x - (LenheartTextClass.GetStringLength(Name) / 2), Y + ENUM_RINDRO_JOB_TITLE_HEIGHT[Job].y + 24, sq_RGBA(255, 255, 255, 250), 1, 1); } } function DrawFace(X, Y) { setClip(X, Y, X + 22, Y + 18); //开始裁切 foreach(AniInfo in DrawInfo) { AniInfo.Ani.DrawIndex(X + ENUM_RINDRO_JOB_FACE_HEIGHT[Job].x, Y + ENUM_RINDRO_JOB_FACE_HEIGHT[Job].y, 0); } releaseClip(); //裁切结束 } } //鬼剑士 //601580026 101550559 // Sassq <- {}; // Sassq[0] <- Rindro_Draw_Character(0, [ // 601550071, // 601560067, // 601570062, // 601500069, // 601510068, // 601540069, // 601520061, // 601530060, // 601580026, // 0, // 27610, // 26058 // ], "rest.ani", "鬼剑士-Kina") // //格斗家 // Sassq[1] <- Rindro_Draw_Character(1, [26373, 102550540, 102560700, 102570504, 102520514, 102500742, 102510739, 102540664, 102580139, 102530474], "rest.ani", "Kina") // //神枪手 // Sassq[2] <- Rindro_Draw_Character(2, [26373, 104550553, 104560725, 104570492, 104520541, 104500750, 104510913, 104540671, 104580148, 104530494], "rest.ani", "Kina") // //魔法师 // Sassq[3] <- Rindro_Draw_Character(3, [26373, 106550521, 106560580, 106570446, 106520529, 106500603, 106510607, 106540583, 106580143, 106530461], "rest.ani", "Kina") // //圣职者 // Sassq[4] <- Rindro_Draw_Character(4, [26373, 108550600, 108560591, 108570687, 108520580, 108500587, 108510590, 108540562, 108580138, 108530560], "rest.ani", "Kina") // //女枪 // Sassq[5] <- Rindro_Draw_Character(5, [26373, 105550431, 105560424, 105570386, 105520415, 105500424, 105510429, 105540408, 105580144, 105530361], "rest.ani", "Kina") // //暗夜 // Sassq[6] <- Rindro_Draw_Character(6, [26373, 109550385, 109560393, 109570369, 109520406, 109500402, 109510414, 109540389, 109580134, 109530355], "rest.ani", "Kina") // //男格斗 // Sassq[7] <- Rindro_Draw_Character(7, [26373, 103550302, 103560311, 103570274, 103520297, 103500297, 103510301, 103540284, 103580128, 103530246], "rest.ani", "Kina") // //男法 // Sassq[8] <- Rindro_Draw_Character(8, [26373, 107550220, 107560223, 107570188, 107520224, 107500233, 107510231, 107540209, 107580129, 107530192], "rest.ani", "Kina")