From b16e8d782021b4303cbe5dd05b1ba6fa8c418cbc Mon Sep 17 00:00:00 2001 From: Lenheart <947330670@qq.com> Date: Tue, 21 Oct 2025 19:21:20 +0800 Subject: [PATCH] =?UTF-8?q?=E9=BC=A0=E6=A0=87=E6=A1=86=E6=9E=B6=E5=AE=8C?= =?UTF-8?q?=E6=88=90=20=E7=AA=97=E5=8F=A3=E4=BA=8B=E4=BB=B6=E6=A1=86?= =?UTF-8?q?=E6=9E=B6=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SquirrelFileConfig.cfg | 8 +++ Tool/Math.nut | 125 ++++++++++++++++++++++++++++++++++ UI/MainUI.nut | 21 +++--- UI/ObjectClass/Actor.nut | 27 ++++++-- UI/ObjectClass/GameWindow.nut | 77 ++++++++++++++------- UI/ObjectClass/WindowNode.nut | 13 ++-- UI/Windows/HUD/Window_hud.nut | 20 ++++++ UI/Windows/System/Cursor.nut | 75 ++++++++++++++++++++ enum.nut | 45 +++++++----- folder-alias.json | 18 +++++ internalInterfaceDoc/func.nut | 15 +++- 11 files changed, 378 insertions(+), 66 deletions(-) create mode 100644 Tool/Math.nut create mode 100644 UI/Windows/HUD/Window_hud.nut create mode 100644 UI/Windows/System/Cursor.nut diff --git a/SquirrelFileConfig.cfg b/SquirrelFileConfig.cfg index 17c46da..c86c899 100644 --- a/SquirrelFileConfig.cfg +++ b/SquirrelFileConfig.cfg @@ -1,4 +1,5 @@ enum.nut +Tool/Math.nut Game/StateMachine/StateMachine.nut @@ -17,5 +18,12 @@ UI/ObjectClass/Actor.nut UI/ObjectClass/WindowNode.nut UI/ObjectClass/GameWindow.nut UI/ObjectClass/Sprite.nut + + + + +UI/Windows/System/Cursor.nut +UI/Windows/HUD/Window_hud.nut + UI/MainUI.nut main.nut \ No newline at end of file diff --git a/Tool/Math.nut b/Tool/Math.nut new file mode 100644 index 0000000..773d223 --- /dev/null +++ b/Tool/Math.nut @@ -0,0 +1,125 @@ +/* +文件名:Math.nut +路径:Tool/Math.nut +创建日期:2025-10-21 18:10 +文件用途:数学工具 +*/ +class Math { + /** + * 取随机值 左闭右闭 + * @function + * @param {integer} Min + * @param {integer} Max + * @returns {integer} + */ + function Rand(Min, Max) { + local In = rand(); + local Ret = (Min + (Max - Min + 1) * (In / (RAND_MAX + 1).tofloat())).tointeger(); + return Ret; + } + + /** + * 随机返回数组中的任意一个数 + * @function + * @param {array} arr + * @returns {any} + */ + function GetRandomElementFromArray(arr) { + if (arr.len() == 0) { + return null; + } + // 生成一个0到数组长度-1之间的随机索引 + local randomIndex = Math.Rand(0, arr.len() - 1); + return arr[randomIndex]; + } + + /** + * 通过坐标获得两点旋转角度 + * @function + * @param {integer} x1 + * @param {integer} y1 + * @param {integer} x2 + * @param {integer} y2 + * @returns {float} + */ + function GetRorateAngleByPos(x1, y1, x2, y2) { + return (atan2((y2 - y1).tofloat(), (x2 - x1).tofloat()) * 180) / PI; + } + + /** + * + * @function + * @param {integer} x1 + * @param {aintegerny} y1 + * @param {integer} x2 + * @param {integer} y2 + * @returns {float} + */ + function GetDistanceByPos(x1, y1, x2, y2) { + return sqrt(pow((x2 - x1).tofloat(), 2) + pow((y2 - y1).tofloat(), 2)); + } + + /** + * 获得两值随时间的匀速运动值 + * @function + * @param {any} sv + * @param {any} ev + * @param {float} currentRate + * @param {float} maxRate + * @returns {*} + */ + function GetUniformVelocity(sv, ev, currentRate, maxRate) { + local rate = currentRate.tofloat() / maxRate.tofloat(); + local varyValue = ev - sv; + return sv + varyValue * rate; + } + + /** + * 获得两值随时间的变速运动值 + * @function + * @param {any} sv + * @param {any} ev + * @param {float} currentRate + * @param {float} maxRate + * @param {any} increaseFeature + * @returns {*} + */ + function GetAccel(sv, ev, currentRate, maxRate, increaseFeature) { + local rate = currentRate.tofloat() / maxRate.tofloat(); + local varyValue = ev - sv; + local increaseRate = 1.0; + if (increaseFeature) { + increaseRate = pow(50, rate) / 50.0; //慢->快 + } else { + // 修正后的减速逻辑计算,例如采用线性变换结合幂次运算来实现更合理的减速效果 + // 先将rate映射到一个更合适的范围(这里从[0,1]映射到[0.1, 1],可调整) + local mappedRate = rate * 0.9 + 0.1; + increaseRate = pow(mappedRate, 2); // 幂次可调整,这里取2来让减速更明显,可根据实际情况修改 + } + return sv + varyValue * increaseRate; + } + + /** + * 计算两个矩形是否相交 + * @function + * @param {any} x1 + * @param {any} y1 + * @param {any} width1 + * @param {any} height1 + * @param {any} x2 + * @param {any} y2 + * @param {any} width2 + * @param {any} height2 + * @returns {boolean} + */ + function IsIntersectRect(x1, y1, width1, height1, x2, y2, width2, height2) { + // 计算矩形1的边界 + local right1 = x1 + width1; + local bottom1 = y1 + height1; + // 计算矩形2的边界 + local right2 = x2 + width2; + local bottom2 = y2 + height2; + // 检查是否有重叠 + return !(right1 < x2 || bottom1 < y2 || x1 > right2 || y1 > bottom2); + } +} diff --git a/UI/MainUI.nut b/UI/MainUI.nut index 99b47f0..4fa248f 100644 --- a/UI/MainUI.nut +++ b/UI/MainUI.nut @@ -6,22 +6,23 @@ */ //主界面UI初始化回调 function _MainUI_Enter_(UI_Scene) { - if (!_SYS_UI_SCENE_Instance_) _SYS_UI_SCENE_Instance_ = Actor(UI_Scene) + if (!_SYS_UI_SCENE_Instance_) _SYS_UI_SCENE_Instance_ = Actor(UI_Scene); + //初始化随机数种子 + srand(time()); - local TestWindow = sq_CreaterWindow("测试窗口", GameWindow) - TestWindow.ResetFoucus() + //初始化鼠标 + Game_Cursor.GetInstance(); - local Sp = Sprite( - "sprite/interface2/worldmap/step_2(area)/step_2(area)_bg.img", - 12 - ) - TestWindow.AddChild(Sp) + local TestWindow = sq_CreaterWindowInstance("HUD窗口", Window_hud, 0, 0, 1280, 720, 0); + TestWindow.ResetFoucus(); } //主界面UI事件回调 -function _MainUI_HandleEvents_(event) {} +function _MainUI_HandleEvents_(EventType, EventData) { + _Global_Windows_Events_(EventType, EventData); +} //主界面UI更新回调 function _MainUI_Update_(deltaTime) { - _Global_Windows_Logic_(deltaTime) + _Global_Windows_Logic_(deltaTime); } //主界面UI退出回调 function _MainUI_Exit_() {} diff --git a/UI/ObjectClass/Actor.nut b/UI/ObjectClass/Actor.nut index 611cb6a..acf084c 100644 --- a/UI/ObjectClass/Actor.nut +++ b/UI/ObjectClass/Actor.nut @@ -6,26 +6,41 @@ */ class Actor extends BaseNode { function _typeof() { - return "Actor" + return "Actor"; } constructor(obj = null) { if (obj) { - base.constructor(obj, false) + base.constructor(obj, false); } else { - base.constructor(sq_CreateActor()) + base.constructor(sq_CreateActor()); } } function AddChild(Act) { - sq_AddChild(this.C_Object, Act.C_Object) + sq_AddChild(this.C_Object, Act.C_Object); } function RemoveChild(Act) { - sq_RemoveChild(this.C_Object, Act.C_Object) + sq_RemoveChild(this.C_Object, Act.C_Object); } - function SetZOrder(Order){ + function SetZOrder(Order) { sq_SetZOrder(this.C_Object, Order); } + + function SetScale(Value, ...) { + if (vargv.len() == 0) + sq_SetScale(this.C_Object, Value); + else if (vargv.len() == 1) + sq_SetScale(this.C_Object, Value, vargv[0]); + } + + function SetPos(Value, ...) { + if (vargv.len() == 0) { + sq_SetPos(this.C_Object, Value); + } else if (vargv.len() == 1) { + sq_SetPos(this.C_Object, Value, vargv[0]); + } + } } diff --git a/UI/ObjectClass/GameWindow.nut b/UI/ObjectClass/GameWindow.nut index cecbd9e..60978e9 100644 --- a/UI/ObjectClass/GameWindow.nut +++ b/UI/ObjectClass/GameWindow.nut @@ -4,36 +4,52 @@ 创建日期:2025-10-18 20:58 文件用途:游戏窗口类 */ -_SYS_UI_SCENE_Instance_ <- null -_SYS_WINDOW_LIST_ <- [] +_SYS_UI_SCENE_Instance_ <- null; +_SYS_WINDOW_LIST_ <- []; class GameWindow extends WindowNode { //窗口名称 - WindowName = "undefined" + WindowName = "undefined"; + //是否活动窗口Flag + IsActiveFlag = false; function _typeof() { - return "GameWindow" + return "GameWindow"; } - constructor(WindowName) { - base.constructor() + constructor(WindowName, gX, gY, gWidth, gHeight, gTitleHeight) { + base.constructor(); } function ResetFoucus() { - SetVisible(true) + SetVisible(true); //遍历全局窗口数组将自己移除重新添加在末尾 foreach (Index, WindowObj in _SYS_WINDOW_LIST_) { if (WindowObj.WindowName == this.WindowName) { - _SYS_WINDOW_LIST_.remove(Index) - break + _SYS_WINDOW_LIST_.remove(Index); + break; } } - _SYS_WINDOW_LIST_.append(this) - SetZOrder(_SYS_WINDOW_LIST_.len()) + _SYS_WINDOW_LIST_.append(this); + SetZOrder(_SYS_WINDOW_LIST_.len()); } - function Proc(Dt) { - + function Proc(Dt) {} + + //鼠标事件回调 + function OnMouseEvent(Type, Data) { + if (!Visible) return; + foreach (Window in Childrens) { + if (Window instanceof WindowNode) Window.OnMouseEvent(Type, Data); + } + } + + //键盘事件回调 + function OnKeyEvent(Type, Data) { + if (!Visible) return; + foreach (Window in Childrens) { + if (Window instanceof WindowNode) Window.OnKeyEvent(Type, Data); + } } } @@ -44,36 +60,36 @@ class GameWindow extends WindowNode { * @param {GameWindow} WindowClass * @returns {any} */ -function sq_CreaterWindow(WindowName, WindowClass) { +function sq_CreaterWindowInstance(WindowName, WindowClass, gX, gY, gWidth, gHeight, gTitleHeight) { foreach (idx, val in _SYS_WINDOW_LIST_) { if (val.WindowName == WindowName) return val; } - local NewWindow = WindowClass(WindowName); + local NewWindow = WindowClass(WindowName, gX, gY, gWidth, gHeight, gTitleHeight); getroottable()._SYS_WINDOW_LIST_.push(NewWindow); return NewWindow; } /** - * - * @function + * + * @function * @param {float} Dt * @returns {void} */ function _Global_Windows_Logic_(Dt) { if (_SYS_UI_SCENE_Instance_) { for (local i = 0; i < _SYS_WINDOW_LIST_.len(); i++) { - local Window = _SYS_WINDOW_LIST_[i] + local Window = _SYS_WINDOW_LIST_[i]; //如果窗口不可见并且 处于演出状态 if (!Window.Visible && Window.PerformanceState) { - Window.PerformanceState = false - _SYS_UI_SCENE_Instance_.RemoveChild(Window) + Window.PerformanceState = false; + _SYS_UI_SCENE_Instance_.RemoveChild(Window); if (Window.DestroyFlag) { _SYS_WINDOW_LIST_.remove(i); i--; } } else if (Window.Visible && !Window.PerformanceState) { - _SYS_UI_SCENE_Instance_.AddChild(Window) + _SYS_UI_SCENE_Instance_.AddChild(Window); Window.PerformanceState = true; } //无论窗口是否显示都需要调用Proc @@ -82,6 +98,19 @@ function _Global_Windows_Logic_(Dt) { } } - - - +function _Global_Windows_Events_(EventType, EventData) { + //先传递鼠标事件 + Game_Cursor.GetInstance().Event(EventType, EventData); + //事件是否被响应Flag + local EventInteractiveFlag = false; + for (local i = _SYS_WINDOW_LIST_.len() - 1; i > -1; i--) { + local Window = _SYS_WINDOW_LIST_[i]; + if (Window.Visible) { + if (EventType == UI_EVENT.MOUSEMOTION || EventType == UI_EVENT.MOUSEBUTTONDOWN || EventType == UI_EVENT.MOUSEBUTTONUP) { + Window.OnMouseEvent(EventType, EventData); + } else if (EventType == UI_EVENT.KEYDOWN || EventType == UI_EVENT.KEYUP) { + Window.OnKeyEvent(EventType, EventData); + } + } + } +} diff --git a/UI/ObjectClass/WindowNode.nut b/UI/ObjectClass/WindowNode.nut index 285fc2a..1d04b4d 100644 --- a/UI/ObjectClass/WindowNode.nut +++ b/UI/ObjectClass/WindowNode.nut @@ -20,24 +20,23 @@ class WindowNode extends Actor { //销毁Flag DestroyFlag = false; - function _typeof() { - return "WindowNode" + return "WindowNode"; } constructor() { - base.constructor() + base.constructor(); //子控件list初始化 - Childrens = [] + Childrens = []; } function SetVisible(Flag) { - Visible = Flag + Visible = Flag; } function AddChild(Act) { - base.AddChild(Act) - Childrens.push(Act) + if (!(Act instanceof WindowNode)) base.AddChild(Act); + Childrens.push(Act); } } diff --git a/UI/Windows/HUD/Window_hud.nut b/UI/Windows/HUD/Window_hud.nut new file mode 100644 index 0000000..6e812e7 --- /dev/null +++ b/UI/Windows/HUD/Window_hud.nut @@ -0,0 +1,20 @@ +/* +文件名:Window_hud.nut +路径:UI/Windows/HUD/Window_hud.nut +创建日期:2025-10-19 20:36 +文件用途: +*/ + +class Window_hud extends GameWindow { + constructor(Name, gX, gY, gWidth, gHeight, gTitleHeight) { + base.constructor(Name, gX, gY, gWidth, gHeight, gTitleHeight); + + InitSprite(); + } + + function InitSprite() { + local Sp = Sprite("sprite/interface2/hud/hud.img", 0); + Sp.SetPos((1280 - 403) / 2, 720 - 75); + AddChild(Sp); + } +} diff --git a/UI/Windows/System/Cursor.nut b/UI/Windows/System/Cursor.nut new file mode 100644 index 0000000..f790da2 --- /dev/null +++ b/UI/Windows/System/Cursor.nut @@ -0,0 +1,75 @@ +/* +文件名:Cursor.nut +路径:UI/Windows/System/Cursor.nut +创建日期:2025-10-21 18:46 +文件用途: +*/ + +class Game_Cursor extends GameWindow { + //鼠标精灵数组 + MouseSprite = null; + //当前鼠标工作ID + CurrentMouseTaskId = 0; + + //鼠标X坐标 + MouseX = 0; + //鼠标Y坐标 + MouseY = 0; + + constructor() { + if (getroottable().rawin("__Game_Cursor__")) { + // 防止重复实例化 + throw "Game_Cursor 不能重复实例化!"; + } + base.constructor("系统鼠标", 0, 0, 1280, 720, 0); + + Init(); + //设置鼠标的层级最高 + this.SetZOrder(10000000); + _SYS_UI_SCENE_Instance_.AddChild(this); + } + + /** + * 静态方法:获取唯一实例 + * @function + * @returns {Game_Cursor} + */ + function GetInstance() { + if (!getroottable().rawin("__Game_Cursor__")) { + // 首次调用时创建实例 + getroottable()["__Game_Cursor__"] <- Game_Cursor(); + } + return getroottable()["__Game_Cursor__"]; + } + + function Init() { + MouseSprite = []; + for (local i = 0; i < 254; i++) { + //初始化鼠标精灵 + local Buffer = Sprite("sprite/interface/newstyle/windows/cursor.img", i); + MouseSprite.push(Buffer); + } + SetNormalTask(0); + } + + /** + * 设置鼠标的普通任务 + * @function + * @returns {void} + */ + function SetNormalTask(TaskId) { + RemoveChild(MouseSprite[CurrentMouseTaskId]); + CurrentMouseTaskId = TaskId; + AddChild(MouseSprite[CurrentMouseTaskId]); + MouseSprite[CurrentMouseTaskId].SetPos(MouseX, MouseY); + } + + //事件 + function Event(EventType, EventData) { + if (EventType == UI_EVENT.MOUSEMOTION) { + MouseX = EventData[0]; + MouseY = EventData[1]; + MouseSprite[CurrentMouseTaskId].SetPos(MouseX, MouseY); + } + } +} diff --git a/enum.nut b/enum.nut index 4f6b5c7..f7315ec 100644 --- a/enum.nut +++ b/enum.nut @@ -6,22 +6,31 @@ */ enum CHARACTERJOB { - SWORDMAN // 男鬼剑士 - FIGHTER // 女格斗家 - GUNNER // 男神枪手 - MAGE // 女魔法师 - PRIEST // 男圣职者 - AT_GUNNER // 女神枪手 - THIEF // 暗夜使者 - AT_FIGHTER // 男格斗家 - AT_MAGE // 男魔法师 - DEMONIC_SWORDMAN // 黑暗武士 - CREATOR_MAGE // 缔造者 - AT_SWORDMAN // 女鬼剑士 - KNIGHT // 守护者 - DEMONIC_LANCER // 魔枪士 - AT_PRIEST // 女圣职者 - GUN_BLADER // 枪剑士 - ARCHER // 弓箭手 + SWORDMAN, // 男鬼剑士 + FIGHTER, // 女格斗家 + GUNNER, // 男神枪手 + MAGE, // 女魔法师 + PRIEST, // 男圣职者 + AT_GUNNER, // 女神枪手 + THIEF, // 暗夜使者 + AT_FIGHTER, // 男格斗家 + AT_MAGE, // 男魔法师 + DEMONIC_SWORDMAN, // 黑暗武士 + CREATOR_MAGE, // 缔造者 + AT_SWORDMAN, // 女鬼剑士 + KNIGHT, // 守护者 + DEMONIC_LANCER, // 魔枪士 + AT_PRIEST, // 女圣职者 + GUN_BLADER, // 枪剑士 + ARCHER, // 弓箭手 MAX // 无 -}; \ No newline at end of file +} + +enum UI_EVENT { + MOUSEMOTION, //鼠标移动 + MOUSEBUTTONDOWN, //鼠标按下 + MOUSEBUTTONUP, //鼠标释放 + MOUSEWHEEL //鼠标滚轮 + KEYDOWN //键盘按下 + KEYUP //键盘释放 +} diff --git a/folder-alias.json b/folder-alias.json index f655ec6..e6f26b8 100644 --- a/folder-alias.json +++ b/folder-alias.json @@ -46,5 +46,23 @@ }, "UI/ObjectClass/WindowNode.nut": { "description": "窗口节点" + }, + "UI/Windows": { + "description": "窗口集合" + }, + "UI/Windows/HUD": { + "description": "血槽" + }, + "UI/Windows/HUD/Window_hud.nut": { + "description": "血槽窗口" + }, + "Tool": { + "description": "工具类" + }, + "UI/Windows/System": { + "description": "系统" + }, + "UI/Windows/System/Cursor.nut": { + "description": "鼠标" } } \ No newline at end of file diff --git a/internalInterfaceDoc/func.nut b/internalInterfaceDoc/func.nut index c6d3b17..eef7b81 100644 --- a/internalInterfaceDoc/func.nut +++ b/internalInterfaceDoc/func.nut @@ -96,4 +96,17 @@ function sq_RegisterDestruction(a,b) {} function sq_CreateSprite(a,b) {} function sq_AddChild(a,b){} function sq_RemoveChild(a,b){} -function sq_SetZOrder(a,b){} \ No newline at end of file +function sq_SetZOrder(a,b){} + +function sq_SetPos(a,...){} +function sq_SetScale(a,...){} + +/** + * + * @function + * @param {any} a + * @param {any} b + * @returns {any} + */ +function pow(a,b){} +