diff --git a/Yosin_Engine.exe b/Yosin_Engine.exe index 51fde45..5234fab 100644 Binary files a/Yosin_Engine.exe and b/Yosin_Engine.exe differ diff --git a/opencv_world4100.dll b/opencv_world4100.dll new file mode 100644 index 0000000..de9b1ec Binary files /dev/null and b/opencv_world4100.dll differ diff --git a/sqr/Core/BaseClass/AnimationClass/AnimationClass.nut b/sqr/Core/BaseClass/AnimationClass/AnimationClass.nut index 7454f33..7ea24c5 100644 --- a/sqr/Core/BaseClass/AnimationClass/AnimationClass.nut +++ b/sqr/Core/BaseClass/AnimationClass/AnimationClass.nut @@ -164,6 +164,13 @@ class Animation extends Actor { return FrameArr[CurrentFrameIndex]; } + //设置描边 + function SetOutline(Flag, Color = 0xffffffff) { + foreach(Index, Sprite in SpriteArr) { + Sprite.SetOutline(Flag, Color); + } + } + function FlushFrame(Index) { //同步当前帧 CurrentFrameIndex = Index; diff --git a/sqr/Core/BaseClass/ScriptManager/ScriptManager.nut b/sqr/Core/BaseClass/ScriptManager/ScriptManager.nut index ef90d4a..6fd069a 100644 --- a/sqr/Core/BaseClass/ScriptManager/ScriptManager.nut +++ b/sqr/Core/BaseClass/ScriptManager/ScriptManager.nut @@ -169,11 +169,9 @@ class GlobaData { if (!Buf) { Buf = ""; } else { - Buf = "<" + Before + "::" + Buf + "`" + getroottable()._Script_Data_.GetLoadString(Buf) + "`>"; + Buf = getroottable()._Script_Data_.GetLoadString(Buf); } - Buf = Buf + "\r\n"; - out += Buf; - break; + return Buf; } case 2: { IO.seek(-4, 'c'); diff --git a/sqr/Core/BaseClass/SpriteObject/SpriteClass.nut b/sqr/Core/BaseClass/SpriteObject/SpriteClass.nut index de6101b..54eb650 100644 --- a/sqr/Core/BaseClass/SpriteObject/SpriteClass.nut +++ b/sqr/Core/BaseClass/SpriteObject/SpriteClass.nut @@ -46,6 +46,11 @@ class CL_SpriteObject extends CL_BaseObject { Sprite_SetMode(this.C_Object, Mode); } + //设置描边 + function SetOutline(Flag, Color = 0xffffffff) { + Sprite_SetOutline(this.C_Object, Flag, Color); + } + //设置裁切 function SetCropRect(Parameter1, Parameter2, ...) { if (vargv.len() == 0) { diff --git a/sqr/Core/UI_Class/UI_Core.nut b/sqr/Core/UI_Class/UI_Core.nut index 8b02939..a1bf5d7 100644 --- a/sqr/Core/UI_Class/UI_Core.nut +++ b/sqr/Core/UI_Class/UI_Core.nut @@ -398,6 +398,8 @@ function _Yosin_Windows_Logic_(Dt, Ui_Layer) { //鼠标点击Flag _Mouse_Click_Flag <- {}; _Yosin_Cursor(); +//特殊鼠标逻辑 +_Yosin_Mouse_Logic_Func_ <- {}; //鼠标逻辑入口 function _Yosin_Windows_Mouse_Logic_(MouseState, Wheel, MousePos_X, MousePos_Y) { @@ -468,9 +470,19 @@ function _Yosin_Windows_Mouse_Logic_(MouseState, Wheel, MousePos_X, MousePos_Y) break; } } - if (Math.IsIntersectRect(MousePos_X, MousePos_Y, 1, 1, Window.X, Window.Y, Window.Width, Window.Height)) return; + if (Math.IsIntersectRect(MousePos_X, MousePos_Y, 1, 1, Window.X, Window.Y, Window.Width, Window.Height)) break; } } + + //可注册的除窗口外的其他事件 + foreach(Func in _Yosin_Mouse_Logic_Func_) { + local ret = Func(MouseState, Wheel, MousePos_X, MousePos_Y); + if (ret == true) return; + } +} +//注册鼠标逻辑函数 +function Reg_Yosin_Mouse_Logic(Flag, Func) { + _Yosin_Mouse_Logic_Func_.rawset(Flag, Func); } //输入逻辑函数Map diff --git a/sqr/SquirrelFileConfig.cfg b/sqr/SquirrelFileConfig.cfg index 7cabece..f36a264 100644 --- a/sqr/SquirrelFileConfig.cfg +++ b/sqr/SquirrelFileConfig.cfg @@ -64,6 +64,7 @@ l:\Yosin_Engine\Yosin&Kiwano_DOF\sqr\User\Object\ActiveObject\StaticObjectClass. l:\Yosin_Engine\Yosin&Kiwano_DOF\sqr\User\Object\ActiveObject\ActiveObjectClass.nut l:\Yosin_Engine\Yosin&Kiwano_DOF\sqr\User\Object\ActiveObject\PassiveObjectClass.nut l:\Yosin_Engine\Yosin&Kiwano_DOF\sqr\User\Object\ActiveObject\MonsterObjectClass.nut +l:\Yosin_Engine\Yosin&Kiwano_DOF\sqr\User\Object\ActiveObject\NpcObjectClass.nut l:\Yosin_Engine\Yosin&Kiwano_DOF\sqr\User\Object\ActiveObject\CharacterObjectClass.nut l:\Yosin_Engine\Yosin&Kiwano_DOF\sqr\User\Object\ActiveObject\CharacterObjectClass_AI.nut diff --git a/sqr/User/Asset/AssetManager.nut b/sqr/User/Asset/AssetManager.nut index f9c1304..e66f57e 100644 --- a/sqr/User/Asset/AssetManager.nut +++ b/sqr/User/Asset/AssetManager.nut @@ -16,6 +16,8 @@ class _AssetManager_ { TownList = null; //装备列表 EquipmentList = null; + //NPC列表 + NpcList = null; function InitMapList() { MapList = ScriptData.GetFileData("map/map.lst", function(DataTable, Data) { @@ -136,6 +138,20 @@ class _AssetManager_ { }); } + function InitNpcList() { + NpcList = ScriptData.GetFileData("npc/npc.lst", function(DataTable, Data) { + while (!Data.Eof()) { + local Key = Data.Get(); + //注册NPC列表 路径写入 数据未读取 + DataTable.rawset(Key, { + Path = Data.Get(), + Data = null + }); + } + if (_DEBUG_) print("加载NPCList完成, 共" + DataTable.len() + "个"); + }); + } + function InitTownList() { TownList = ScriptData.GetFileData("town/town.lst", function(DataTable, Data) { while (!Data.Eof()) { @@ -159,6 +175,8 @@ class _AssetManager_ { InitCharacter(); //初始化装备列表 InitEquipmentList(); + //初始化NPC列表 + InitNpcList(); getroottable().AssetManager <- this; @@ -250,4 +268,51 @@ class _AssetManager_ { EquipmentList[Idx].Data = m_data; return m_data; } + + + //Public:: + + //获取NPC信息 + function GetNpc(Idx) { + //如果没有这个NPC则返回 + if (!(NpcList.rawin(Idx))) return; + //如果NPC数据已经读取过存在了则直接返回 + if (NpcList[Idx].Data) return NpcList[Idx].Data; + local Path = NpcList[Idx].Path; + local m_data = ScriptData.GetFileData("npc/" + Path, function(DataTable, Data) { + DataTable.DirPath <- DataTable.filepath.slice(0, DataTable.filepath.lastfind("/") + 1); + while (!Data.Eof()) { + local Pack = Data.Get(); + //各种头像 + if (Pack == "[small face]" || Pack == "[big face]" || Pack == "[popup face]") { + local RealKey = Pack.slice(1, Pack.find(" face")) + "_face"; + DataTable[RealKey] <- { + img = Data.Get().tolower(), + idx = Data.Get() + } + } else if (Pack == "[field animation]") { + DataTable.field_animation <- DataTable.DirPath + Data.Get().tolower(); + } else if (Pack == "[field wav]") { + DataTable.field_wav <- Data.Get(); + } else if (Pack == "[popup wav]") { + DataTable.popup_wav <- [Data.Get(), Data.Get()]; + } else if (Pack == "[name]") { + DataTable.name <- Data.Get(); + } else if (Pack == "[field name]") { + DataTable.field_name <- Data.Get(); + } + //功能 + else if (Pack == "[role]") { + DataTable.role <- {}; + while (true) { + local Ret = Data.Get(); + if (Ret == "[/role]") break; + DataTable.role.rawset(Ret.slice(1, -1).tolower(), Data.Get()); + } + } + } + }); + NpcList[Idx].Data = m_data; + return m_data; + } } \ No newline at end of file diff --git a/sqr/User/Asset/FontAsset.nut b/sqr/User/Asset/FontAsset.nut index 21a3ed9..916519c 100644 --- a/sqr/User/Asset/FontAsset.nut +++ b/sqr/User/Asset/FontAsset.nut @@ -11,7 +11,7 @@ class _FontAssetManager_ { function InitFont() { //普通宋体小字 // Font.PreLoad("新宋体"); - Font("新宋体", 11.5).Register(0); + Font("宋体", 11.5).Register(0); } constructor() { diff --git a/sqr/User/Object/ActiveObject/CharacterObjectClass.nut b/sqr/User/Object/ActiveObject/CharacterObjectClass.nut index 4dde1e4..e2da571 100644 --- a/sqr/User/Object/ActiveObject/CharacterObjectClass.nut +++ b/sqr/User/Object/ActiveObject/CharacterObjectClass.nut @@ -64,6 +64,7 @@ class GameObject.Character extends GameObject.ActiveObject { //分配控制器 Controller = Object_Controller(this); + } diff --git a/sqr/User/Object/ActiveObject/NpcObjectClass.nut b/sqr/User/Object/ActiveObject/NpcObjectClass.nut new file mode 100644 index 0000000..921af75 --- /dev/null +++ b/sqr/User/Object/ActiveObject/NpcObjectClass.nut @@ -0,0 +1,88 @@ +/* +文件名:NpcObjectClass.nut +路径:User/Object/ActiveObject/NpcObjectClass.nut +创建日期:2024-12-28 11:11 +文件用途:NPC类 +*/ +class GameObject.NPC extends GameObject.BaseClass { + + //ID + Id = 0; + //信息 + Info = null; + //Ani动画 + Ani = null; + //名字 + Name = null; + + //识别高度 + IdentifyHeight = 0; + //识别宽度 + IdentifyWidth = 0; + + //是否悬停 + IsHover = false; + + function _typeof() { + return "npc"; + } + + //初始化装配 + function InitAssembly(IndexKey, SetKey, Func) { + if (Info.rawin(IndexKey)) { + this[SetKey] = Func(Info[IndexKey]); + } + } + + constructor(Id) { + this.Id = Id; + base.constructor(); + Info = AssetManager.GetNpc(Id); + if (Info) { + //构造Ani + InitAssembly("field_animation", "Ani", function(Data) { + local Ani = Animation(Data); + Addchild(Ani); + local Size = Ani.GetSize(); + IdentifyHeight = Size.h; + IdentifyWidth = Size.w; + return Ani; + }); + //构造名字 + InitAssembly("name", "Name", function(Data) { + //创建名字对象 + local NameObj = FontAssetManager.GenerateNormal(Data, true, { + color = sq_RGBA(242, 209, 175, 255), + }); + local Height = Ani ? Ani.GetSize().h : 0; + NameObj.SetPosition(0 - (NameObj.GetSize().w / 2), -Height - 25); + NameObj.SetZOrder(80000); + Addchild(NameObj); + return NameObj; + }); + } + + } + + function OnMouseLogic(MouseState, Wheel, MousePos_X, MousePos_Y) { + //悬停事件 + if (!IsHover) { + IsHover = true; + //设置Ani描边 + Ani.SetOutline(true, sq_RGBA(155, 255, 0, 250)); + //设置鼠标 + Yosin_Cursor.Change(120); + } + } + + function OutMouseLogic() { + //悬停事件 + if (IsHover) { + IsHover = false; + Ani.SetOutline(false); + //设置鼠标 + Yosin_Cursor.Change(0); + } + } + +} \ No newline at end of file diff --git a/sqr/User/Object/Map/MapObject.nut b/sqr/User/Object/Map/MapObject.nut index ed39fe6..38771b3 100644 --- a/sqr/User/Object/Map/MapObject.nut +++ b/sqr/User/Object/Map/MapObject.nut @@ -202,7 +202,7 @@ class Map extends Actor { local realpath = m_data.dirpath + path.tolower(); local TileObj = Tile(realpath); TileObj.SetAnchor(0.0, 0.0); - TileObj.SetPosition(pos * 224, -120 - m_data.background_pos); + TileObj.SetPosition(pos * 224, -200 - m_data.background_pos); LayerObject.bottom.Addchild(TileObj); } //默认地板 + 摄像机偏移 + 默认需要有一个40的添加地板 @@ -220,7 +220,7 @@ class Map extends Actor { local TileObj = Tile(realpath); TileObj.SetAnchor(0.0, 0.0); //根据基础地板的数量判断是第几排 - TileObj.SetPosition((pos % NormalTileCount) * 224, 560 - 120 - m_data.background_pos + ((pos / NormalTileCount) * 40)); + TileObj.SetPosition((pos % NormalTileCount) * 224, 560 - 200 - m_data.background_pos + ((pos / NormalTileCount) * 40)); LayerObject.bottom.Addchild(TileObj); } } @@ -266,6 +266,21 @@ class Map extends Actor { } + //初始化NPC + function InitNPC() { + if (!m_data.rawin("npc")) return; + local Arr = []; + foreach(pos, info in m_data.npc) { + local NPCobj = GameObject.NPC(info.id); + NPCobj.SetDirection(info.direction); + NPCobj.SetPosition(info.xpos, info.ypos, info.zpos); + Arr.push(NPCobj); + AddObject(NPCobj); + } + //构造完成直接赋值对象 + m_data.npc = Arr; + } + //添加对象 function AddObject(obj, IsPlayer = false) { @@ -287,6 +302,8 @@ class Map extends Actor { BackGroundMusic[SoundName] <- BgMusic; } } + } else if (typeof obj == "npc") { + LayerObject.normal.Addchild(obj); } } @@ -373,6 +390,10 @@ class Map extends Actor { InitBackgroundAnimation(); //初始化场景Ani InitAnimation(); + //初始化NPC + InitNPC(); + //注册鼠标判定逻辑 + Reg_Yosin_Mouse_Logic("MapMLg_" + C_Object, OnMouseLogic.bindenv(this)); //设置摄像机的最大可行区域 m_camera.MovableAreaX = m_length; @@ -398,6 +419,36 @@ class Map extends Actor { } } + function OnMouseLogic(MouseState, Wheel, MousePos_X, MousePos_Y) { + //判断是人物所在的地图 + if (ClientCharacter && this.C_Object == ClientCharacter.MySelfMap.C_Object) { + local Arr = []; + //遍历全部NPC位置 + foreach(index, Npcobj in m_data.npc) { + //获取NPC的屏幕位置 + local NPCpos = Npcobj.GetWorldPosition(); + //在屏幕中的才添加比对 这里只判断了X轴 + if (NPCpos.x > -20 && NPCpos.y< 1086) { + Arr.push(NPCpos.x - Npcobj.IdentifyWidth / 2); + Arr.push(NPCpos.y - Npcobj.IdentifyHeight); + Arr.push(Npcobj.IdentifyWidth); + Arr.push(Npcobj.IdentifyHeight); + } + } + local Index = Math.PointIsInWhichRectangle(MousePos_X, MousePos_Y, Arr); + //有事件发生的NPC对象 + if (Index != -1) { + return m_data.npc[Index].OnMouseLogic(MouseState, Wheel, MousePos_X, MousePos_Y); + } else { + foreach(Npcobj in m_data.npc) { + Npcobj.OutMouseLogic(); + } + return null; + } + } + return null; + } + //判断区域是否可行 function CheckMovableArea(gx, gxoffset, gy, gyoffset) { local pos = { diff --git a/sqr/User/Object/Map/TileObject.nut b/sqr/User/Object/Map/TileObject.nut index b99045a..085b6e6 100644 --- a/sqr/User/Object/Map/TileObject.nut +++ b/sqr/User/Object/Map/TileObject.nut @@ -10,6 +10,7 @@ class Tile extends CL_SpriteObject { function InitData(path) { m_data = ScriptData.GetFileData(path, function(DataTable, Data) { + DataTable.pos <- 0; while (!Data.Eof()) { local Pack = Data.Get(); if (Pack == "[IMAGE]") { @@ -42,4 +43,19 @@ class Tile extends CL_SpriteObject { } } } + + //设置坐标 + function SetPosition(Value, ...) { + if (vargv.len() == 0) { + Value.y += m_data.pos; + X = Value.x; + Y = Value.y; + BaseObject_SetPosition(this.C_Object, Value); + } else if (vargv.len() == 1) { + vargv[0] += m_data.pos; + X = Value; + Y = vargv[0]; + BaseObject_SetPosition(this.C_Object, Value, vargv[0]); + } + } } \ No newline at end of file diff --git a/sqr/User/Stage/TestStage.nut b/sqr/User/Stage/TestStage.nut index b4b752b..e9a3bcf 100644 --- a/sqr/User/Stage/TestStage.nut +++ b/sqr/User/Stage/TestStage.nut @@ -14,67 +14,54 @@ function TestStage() { // //大背景 - // local BackGround = CL_SpriteObject("sprite/interface2/charactercreatever2/characterbackground.img", 14); + // local BackGround = CL_SpriteObject("sprite/map/npc/2019_halloween_blossom_normal.img", 0); + // BackGround.SetPosition(300, 150); + // BackGround.SetOutline(true); // T.Addchild(BackGround); - // //登录按钮文本 - // local TextActor = TextActor(0, { - // color = sq_RGBA(186, 147, 97, 255) - // }); - // TextActor.SetText("测试文字"); - // TextActor.SetPosition(200, 200); - // TextActor.SetZOrder(1000000); - // TextActor.SetOutline(); - // T.Addchild(TextActor); // local Fontobj = Font(); + // local NPCobj = GameObject.NPC(2); + // NPCobj.SetPosition(400, 400, 0); + // T.Addchild(NPCobj); - // local TownObj = Town(1); + local TownObj = Town(1); + local Charc = GameObject.CreateCharacter(0, [101590007, 27675, 601500060, 601550060, 601560058, 601570053, 601520052, 601500060, 601510059, 601530051, 601540060, 601580023]); + TownObj.AddObject(Charc, true); + ClientCharacter = Charc; - // // local MapObj = Map("map/cataclysm/town/seria_room/elvengard.map"); - // // // local MapObj = Map("map/cataclysm/town/hendonmyre/new_backstreet_2.map"); - // // // local MapObj = Map("map/cataclysm/town/seria_room/elvengard.map"); - // // // local MapObj = Map("map/cataclysm/town/sainthorn_heaven/sainthorn_heaven_ship_rear_down.map"); - // // T.Addchild(MapObj); - - // local Charc = GameObject.CreateCharacter(0, [101590007, 27675, 601500060, 601550060, 601560058, 601570053, 601520052, 601500060, 601510059, 601530051, 601540060, 601580023]); - // // Charc.SetPosition(356, 250, 0); - // // Charc.SetAnimation("RestAni"); - // TownObj.AddObject(Charc, true); - - - local Window = Sq_CreateWindow(_Select_Character_Window, "选择角色界面窗口", 0, 0, 1066, 600, 0); - local T = { - loginImg = 1, - charac = [{ - lv = 90, - name = "倾泪寒倾泪寒倾泪寒倾泪寒倾泪寒倾泪寒倾泪寒倾泪寒倾泪寒倾泪寒倾泪寒", - job = 0, - equip = [101020001, 601500060, 601550060, 601560058, 601570053, 601520052, 601500060, 601510059, 601530051, 601540060, 601580023, 609590003] - }, { - lv = 90, - name = "倾泪寒222", - job = 0, - equip = [101020023, 601500059, 601550059, 601560057, 601570052, 601520051, 601500059, 601510058, 601530050, 601540059, 601580022, 609590003] - }, { - lv = 90, - name = "Kina", - job = 0, - equip = [101020026, 601500058, 601550058, 601560056, 601570051, 601520050, 601500058, 601510057, 601530049, 601540058, 601580021, 609590003] - }, { - lv = 90, - name = "测试角色", - job = 0, - equip = [101020037, 601500061, 601550061, 601560059, 601570054, 601520053, 601500061, 601510060, 601530052, 601540061, 601580024, 609590003] - }, { - lv = 90, - name = "测试角色2号", - job = 0, - equip = [601020007, 601500060, 601550060, 601560058, 601570053, 601520052, 601500060, 601510059, 601530051, 601540060, 601580023, 609590003] - }] - }; - Window.Init(T); + // local Window = Sq_CreateWindow(_Select_Character_Window, "选择角色界面窗口", 0, 0, 1066, 600, 0); + // local T = { + // loginImg = 1, + // charac = [{ + // lv = 90, + // name = "倾泪寒", + // job = 0, + // equip = [101020001, 601500060, 601550060, 601560058, 601570053, 601520052, 601500060, 601510059, 601530051, 601540060, 601580023, 609590003] + // }, { + // lv = 90, + // name = "倾泪寒222", + // job = 0, + // equip = [101020023, 601500059, 601550059, 601560057, 601570052, 601520051, 601500059, 601510058, 601530050, 601540059, 601580022, 609590003] + // }, { + // lv = 90, + // name = "Kina", + // job = 0, + // equip = [101020026, 601500058, 601550058, 601560056, 601570051, 601520050, 601500058, 601510057, 601530049, 601540058, 601580021, 609590003] + // }, { + // lv = 90, + // name = "测试角色", + // job = 0, + // equip = [101020037, 601500061, 601550061, 601560059, 601570054, 601520053, 601500061, 601510060, 601530052, 601540061, 601580024, 609590003] + // }, { + // lv = 90, + // name = "测试角色2号", + // job = 0, + // equip = [601020007, 601500060, 601550060, 601560058, 601570053, 601520052, 601500060, 601510059, 601530051, 601540060, 601580023, 609590003] + // }] + // }; + // Window.Init(T); // local Actorobj = Actor(); // Actorobj.ShowBorder(true); @@ -93,4 +80,5 @@ function TestStage() { // print(ObjectCount); // Sq_CreateWindow(_CreateCharacter, "创建角色界面窗口", 0, 0, 1066, 600, 0); + } \ No newline at end of file diff --git a/sqr/folder-alias.json b/sqr/folder-alias.json index 2abc671..748d940 100644 --- a/sqr/folder-alias.json +++ b/sqr/folder-alias.json @@ -238,5 +238,8 @@ }, "User/UI/Window/3_Top_tool.nut": { "description": "顶部工具条" + }, + "User/Object/ActiveObject/NpcObjectClass.nut": { + "description": "NPC对象" } } \ No newline at end of file