12 Commits

Author SHA1 Message Date
64659ae536 Merge pull request '加入文本精灵' (#5) from Lenheart into master
Reviewed-on: http://49.234.27.222:3000/Lenheart/DNF_DEV_SQR/pulls/5
2025-10-25 15:54:07 +08:00
89899a3799 加入文本精灵 2025-10-25 15:51:53 +08:00
efb45d7075 Merge pull request '新增画布类,三联,九宫格控件' (#4) from Lenheart into master
Reviewed-on: http://49.234.27.222:3000/Lenheart/DNF_DEV_SQR/pulls/4
2025-10-25 13:43:27 +08:00
77fe539809 新增画布类,三联,九宫格控件 2025-10-25 13:42:36 +08:00
220bd2a687 Merge pull request '控件框架基础引入' (#3) from Lenheart into master
Reviewed-on: http://49.234.27.222:3000/Lenheart/DNF_DEV_SQR/pulls/3
2025-10-21 23:06:36 +08:00
5d78244ef0 控件框架基础引入 2025-10-21 23:06:06 +08:00
3d5b8bb4d5 Merge pull request '鼠标框架完成 窗口事件框架完成' (#2) from Lenheart into master
Reviewed-on: http://49.234.27.222:3000/Lenheart/DNF_DEV_SQR/pulls/2
2025-10-21 19:22:11 +08:00
b16e8d7820 鼠标框架完成 窗口事件框架完成 2025-10-21 19:21:20 +08:00
2686136f72 Merge pull request '1111' (#1) from Lenheart into master
Reviewed-on: http://49.234.27.222:3000/Lenheart/DNF_DEV_SQR/pulls/1
2025-10-18 21:41:27 +08:00
cfa9e279e5 1111 2025-10-18 21:39:57 +08:00
ed376a4825 增加文档 2025-10-18 16:14:25 +08:00
a753cf4998 增加文档 2025-10-18 15:49:45 +08:00
30 changed files with 1992 additions and 126 deletions

20
.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,20 @@
{
// 使用 IntelliSense 了解相关属性。
// 悬停以查看现有属性的描述。
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "squirrel",
"request": "attach",
"name": "Server",
"port": 2222
},
{
"type": "squirrel",
"request": "attach",
"name": "Client",
"port": 2222
}
]
}

View File

@@ -8,64 +8,65 @@
/** /**
* *
* @function * @function
* @param {ActiveObject} obj * @param {CharacterObject} obj
* @returns {void} * @returns {void}
*/ */
function checkCanChangeState_Character_Move(obj) { function checkCanChangeState_Character_Move(obj) {
//获取当前状态 //获取当前状态
local CurState = obj.GetState(); local CurState = obj.GetState()
//得到摇杆的数据 X 和 Y的范围 -1.0 ~ 1.0 //得到摇杆的数据 X 和 Y的范围 -1.0 ~ 1.0
local arr = obj.GetVars("_move_data_", "float"); local arr = obj.GetVars("_move_data_", "float")
if (fabs(arr[0]) > 0.35 || fabs(arr[1]) > 0.35) { if (fabs(arr[0]) > 0.35 || fabs(arr[1]) > 0.35) {
return true; return true
} else return false; } else return false
} }
/** /**
* *
* @function * @function
* @param {ActiveObject} obj * @param {CharacterObject} obj
* @returns {void} * @returns {void}
*/ */
function SetState_Character_Move(obj) { function SetState_Character_Move(obj) {
//获取移动数据 //获取移动数据
local arr = obj.GetVars("_move_data_", "float"); local arr = obj.GetVars("_move_data_", "float")
//设置人物朝向 摇杆X轴大于0则朝右小于0则朝左 //设置人物朝向 摇杆X轴大于0则朝右小于0则朝左
local SetValue = arr[0] > 0 ? 0 : 1; local SetValue = arr[0] > 0 ? 0 : 1
if (SetValue != obj.GetDirection()) { if (SetValue != obj.GetDirection()) {
if (fabs(arr[0]) > 0.35) obj.SetDirection(SetValue); if (fabs(arr[0]) > 0.35) obj.SetDirection(SetValue)
//设置动作 //设置动作
obj.SetAction("move"); obj.SetAction("move")
} else { } else {
if (obj.GetState() != 1) obj.SetAction("move"); if (obj.GetState() != 1) obj.SetAction("move")
} }
local Speed = 250; local Speed = 250
local Dir = obj.GetDirection(); local Dir = obj.GetDirection();
local Pos = obj.GetPosition(); local Pos = obj.GetPosition();
local XOffset = null; local XOffset
if (fabs(arr[0]) > 0.35) XOffset = arr[0] > 0 ? Speed : -Speed; if (fabs(arr[0]) > 0.35) XOffset = arr[0] > 0 ? Speed : -Speed
else XOffset = 0; else XOffset = 0
local YOffset = null; local YOffset
//当摇杆Y轴大于0.35或小于-0.35时设置Y轴偏移量 //当摇杆Y轴大于0.35或小于-0.35时设置Y轴偏移量
if (fabs(arr[1]) > 0.35) YOffset = arr[1] > 0 ? Speed : -Speed; if (fabs(arr[1]) > 0.35) YOffset = arr[1] > 0 ? Speed : -Speed
else YOffset = 0; else YOffset = 0
obj.SetSpeed(XOffset, YOffset, null); obj.SetSpeed(XOffset, YOffset, null)
} }
/** /**
* *
* @function * @function
* @param {ActiveObject} obj * @param {CharacterObject} obj
* @param {integer} DeltaTime * @param {integer} DeltaTime
* @returns {void} * @returns {void}
*/ */
function ProcState_Character_Move(obj, DeltaTime) { function ProcState_Character_Move(obj, DeltaTime) {
//获取移动数据 //获取移动数据
local arr = obj.GetVars("_move_data_", "float"); local arr = obj.GetVars("_move_data_", "float")
if (arr[0] == 0 && arr[1] == 0) { if (arr[0] == 0 && arr[1] == 0) {
obj.SetState(0); obj.SetState(0)
} }
} }

View File

@@ -5,11 +5,23 @@
文件用途:角色站立状态 文件用途:角色站立状态
*/ */
/**
*
* @function
* @param {CharacterObject} obj
* @returns {boolean}
*/
function checkCanChangeState_Character_Rest(obj) { function checkCanChangeState_Character_Rest(obj) {
return true; return true;
} }
/**
*
* @function
* @param {CharacterObject} obj
* @returns {void}
*/
function SetState_Character_Rest(obj) { function SetState_Character_Rest(obj) {
//设置动作 //设置动作
obj.SetAction("rest"); obj.SetAction("rest");
@@ -17,6 +29,13 @@ function SetState_Character_Rest(obj) {
obj.SetSpeed(0, 0, null); obj.SetSpeed(0, 0, null);
} }
/**
*
* @function
* @param {CharacterObject} obj
* @param {integer} DeltaTime
* @returns {void}
*/
function ProcState_Character_Rest(obj, DeltaTime) { function ProcState_Character_Rest(obj, DeltaTime) {
} }

View File

@@ -1,6 +1,5 @@
/** /**
* Description placeholder * Description placeholder
* @global
* @param {*} Object * @param {*} Object
*/ */
class ActiveObject extends BaseObject { class ActiveObject extends BaseObject {
@@ -9,7 +8,7 @@ class ActiveObject extends BaseObject {
} }
/** /**
* * 设置三轴速度
* @function * @function
* @param {integer} x * @param {integer} x
* @param {integer} y * @param {integer} y
@@ -25,7 +24,7 @@ class ActiveObject extends BaseObject {
} }
/** /**
* * 获取三轴速度
* @function * @function
* @returns {any} * @returns {any}
*/ */

View File

@@ -11,16 +11,16 @@ class BaseObject {
} }
/** /**
* * 获取坐标
* @function * @function
* @returns {any} * @returns {any}
*/ */
function GetPosition() { function GetPosition() {
return sq_GetPosition(C_Object); return sq_GetPosition(C_Object);
} }
//
/** /**
* * 设置坐标
* @function * @function
* @param {integer} x * @param {integer} x
* @param {integer} y * @param {integer} y
@@ -32,22 +32,22 @@ class BaseObject {
} }
/** /**
* * 获取储存器
* @function * @function
* @param {string} Name * @param {string} Name
* @param {any} Type * @param {string} Type
* @returns {any} * @returns {array}
*/ */
function GetVars(Name, Type) { function GetVars(Name, Type) {
return sq_GetVars(C_Object, Name, Type); return sq_GetVars(C_Object, Name, Type);
} }
/** /**
* * 设置储存器
* @function * @function
* @param {string} Name * @param {string} Name
* @param {any} Type * @param {any} Type
* @param {any} Value * @param {array} Value
* @returns {void} * @returns {void}
*/ */
function SetVars(Name, Type, Value) { function SetVars(Name, Type, Value) {
@@ -55,7 +55,7 @@ class BaseObject {
} }
/** /**
* * 获取方向
* @function * @function
* @returns {integer} * @returns {integer}
*/ */
@@ -64,7 +64,7 @@ class BaseObject {
} }
/** /**
* * 设置方向
* @function * @function
* @param {integer} Dir * @param {integer} Dir
* @returns {void} * @returns {void}

View File

@@ -4,35 +4,35 @@
*/ */
class CharacterObject extends ActiveObject { class CharacterObject extends ActiveObject {
constructor(Object) { constructor(Object) {
base.constructor(Object); base.constructor(Object)
} }
/** /**
* * 获取状态
* @function * @function
* @returns {*} * @returns {integer} 状态编号
*/ */
function GetState() { function GetState() {
return sq_GetState(C_Object); return sq_GetState(C_Object)
} }
/** /**
* * 设置状态
* @function * @function
* @param {integer} State * @param {integer} State
* @returns {void} * @returns {void}
*/ */
function SetState(State) { function SetState(State) {
sq_SetState(C_Object, State); sq_SetState(C_Object, State)
} }
/** /**
* * 设置动作
* @function * @function
* @param {any} key * @param {string} key
* @returns {void} * @returns {void}
*/ */
function SetAction(key) { function SetAction(key) {
sq_SetAction(C_Object, key); sq_SetAction(C_Object, key)
} }
} }

View File

@@ -27,7 +27,7 @@ class StateMachine {
/** /**
* 静态方法:获取唯一实例 * 静态方法:获取唯一实例
* @function * @function
* @returns {table} * @returns {StateMachine}
*/ */
function GetInstance() { function GetInstance() {
if (!getroottable().rawin("__StateMachine__")) { if (!getroottable().rawin("__StateMachine__")) {
@@ -91,6 +91,7 @@ function StateMachine_SetState(C_Object, Job, State) {
return false; return false;
} }
function StateMachine_ProcState(C_Object, Job, State, DeltaTime) { function StateMachine_ProcState(C_Object, Job, State, DeltaTime) {
//获取状态信息 //获取状态信息
local StateInfo = StateMachine.GetInstance().GetStateInfo(Job, State); local StateInfo = StateMachine.GetInstance().GetStateInfo(Job, State);

View File

@@ -1,4 +1,7 @@
enum.nut enum.nut
Tool/Math.nut
Tool/Json.nut
Tool/Common.nut
Game/StateMachine/StateMachine.nut Game/StateMachine/StateMachine.nut
@@ -12,5 +15,26 @@ Game/CharacterScript/Common/Rest.nut
Game/CharacterScript/Common/Move.nut Game/CharacterScript/Common/Move.nut
UI/ObjectClass/BaseNode.nut
UI/ObjectClass/Actor.nut
UI/ObjectClass/WindowNode.nut
UI/ObjectClass/GameWindow.nut
UI/ObjectClass/GameWidget.nut
UI/ObjectClass/Text.nut
UI/ObjectClass/Sprite.nut
UI/ObjectClass/Canvas.nut
UI/Windows/Widget/BaseWidget.nut
UI/Windows/Widget/TripleCav.nut
UI/Windows/Widget/NineGridCav.nut
UI/Windows/System/Cursor.nut
UI/Windows/System/NotiBox.nut
UI/Windows/HUD/Window_hud.nut
UI/MainUI.nut UI/MainUI.nut
main.nut main.nut

41
Tool/Common.nut Normal file
View File

@@ -0,0 +1,41 @@
/*
文件名:Common.nut
路径:Tool/Common.nut
创建日期:2025-10-25 00:05
文件用途:工具类
*/
function print(Object) {
switch (typeof Object) {
case "table":
case "array": {
local str = Json.Encode(Object);
sq_OutPutTable(str);
break;
}
case "string":
case "integer": {
output(Object);
break;
}
default:
output(Object);
break;
}
}
/**
* 返回颜色的十六进制数
* @function
* @param {any} R
* @param {any} G
* @param {any} B
* @param {any} A
* @returns {*}
*/
function sq_RGBA(R, G, B, A) {
R = R.tointeger();
G = G.tointeger();
B = B.tointeger();
A = A.tointeger();
return (A << 24) + (R << 16) + (G << 8) + B;
}

702
Tool/Json.nut Normal file
View File

@@ -0,0 +1,702 @@
/**
* JSON Parser
* @package JSONParser
*/
class JSONParser {
// should be the same for all components within JSONParser package
static version = "1.0.1";
/**
* Parse JSON string into data structure
*
* @param {string} str
* @param {function({string} value[, "number"|"string"])|null} converter
* @return {*}
*/
function parse(str, converter = null) {
local state;
local stack = []
local container;
local key;
local value;
// actions for string tokens
local string = {
go = function() {
state = "ok";
},
firstokey = function() {
key = value;
state = "colon";
},
okey = function() {
key = value;
state = "colon";
},
ovalue = function() {
value = this._convert(value, "string", converter);
state = "ocomma";
}.bindenv(this),
firstavalue = function() {
value = this._convert(value, "string", converter);
state = "acomma";
}.bindenv(this),
avalue = function() {
value = this._convert(value, "string", converter);
state = "acomma";
}.bindenv(this)
};
// the actions for number tokens
local number = {
go = function() {
state = "ok";
},
ovalue = function() {
value = this._convert(value, "number", converter);
state = "ocomma";
}.bindenv(this),
firstavalue = function() {
value = this._convert(value, "number", converter);
state = "acomma";
}.bindenv(this),
avalue = function() {
value = this._convert(value, "number", converter);
state = "acomma";
}.bindenv(this)
};
// action table
// describes where the state machine will go from each given state
local action = {
"{": {
go = function() {
stack.push({
state = "ok"
});
container = {};
state = "firstokey";
},
ovalue = function() {
stack.push({
container = container,
state = "ocomma",
key = key
});
container = {};
state = "firstokey";
},
firstavalue = function() {
stack.push({
container = container,
state = "acomma"
});
container = {};
state = "firstokey";
},
avalue = function() {
stack.push({
container = container,
state = "acomma"
});
container = {};
state = "firstokey";
}
},
"}": {
firstokey = function() {
local pop = stack.pop();
value = container;
container = ("container" in pop) ? pop.container : null;
key = ("key" in pop) ? pop.key : null;
state = pop.state;
},
ocomma = function() {
local pop = stack.pop();
container[key] <- value;
value = container;
container = ("container" in pop) ? pop.container : null;
key = ("key" in pop) ? pop.key : null;
state = pop.state;
}
},
"[": {
go = function() {
stack.push({
state = "ok"
});
container = [];
state = "firstavalue";
},
ovalue = function() {
stack.push({
container = container,
state = "ocomma",
key = key
});
container = [];
state = "firstavalue";
},
firstavalue = function() {
stack.push({
container = container,
state = "acomma"
});
container = [];
state = "firstavalue";
},
avalue = function() {
stack.push({
container = container,
state = "acomma"
});
container = [];
state = "firstavalue";
}
},
"]": {
firstavalue = function() {
local pop = stack.pop();
value = container;
container = ("container" in pop) ? pop.container : null;
key = ("key" in pop) ? pop.key : null;
state = pop.state;
},
acomma = function() {
local pop = stack.pop();
container.push(value);
value = container;
container = ("container" in pop) ? pop.container : null;
key = ("key" in pop) ? pop.key : null;
state = pop.state;
}
},
":": {
colon = function() {
// Check if the key already exists
// NOTE previous code used 'if (key in container)...'
// but this finds table ('container') member methods too
local err = false;
foreach(akey, avalue in container) {
if (akey == key) err = true;
break
}
if (err) throw "Duplicate key \"" + key + "\"";
state = "ovalue";
}
},
",": {
ocomma = function() {
container[key] <- value;
state = "okey";
},
acomma = function() {
container.push(value);
state = "avalue";
}
},
"true": {
go = function() {
value = true;
state = "ok";
},
ovalue = function() {
value = true;
state = "ocomma";
},
firstavalue = function() {
value = true;
state = "acomma";
},
avalue = function() {
value = true;
state = "acomma";
}
},
"false": {
go = function() {
value = false;
state = "ok";
},
ovalue = function() {
value = false;
state = "ocomma";
},
firstavalue = function() {
value = false;
state = "acomma";
},
avalue = function() {
value = false;
state = "acomma";
}
},
"null": {
go = function() {
value = null;
state = "ok";
},
ovalue = function() {
value = null;
state = "ocomma";
},
firstavalue = function() {
value = null;
state = "acomma";
},
avalue = function() {
value = null;
state = "acomma";
}
}
};
//
state = "go";
stack = [];
// current tokenizeing position
local start = 0;
try {
local
result,
token,
tokenizer = _JSONTokenizer();
while (token = tokenizer.nextToken(str, start)) {
if ("ptfn" == token.type) {
// punctuation/true/false/null
action[token.value][state]();
} else if ("number" == token.type) {
// number
value = token.value;
number[state]();
} else if ("string" == token.type) {
// string
value = tokenizer.unescape(token.value);
string[state]();
}
start += token.length;
}
} catch (e) {
state = e;
}
// check is the final state is not ok
// or if there is somethign left in the str
if (state != "ok" || regexp("[^\\s]").capture(str, start)) {
local min = @(a, b) a< b ? a : b;
local near = str.slice(start, min(str.len(), start + 10));
throw "JSON Syntax Error near `" + near + "`";
}
return value;
}
/**
* Convert strings/numbers
* Uses custom converter function
*
* @param {string} value
* @param {string} type
* @param {function|null} converter
*/
function _convert(value, type, converter) {
if ("function" == typeof converter) {
// # of params for converter function
local parametercCount = 2;
// .getinfos() is missing on ei platform
if ("getinfos" in converter) {
parametercCount = converter.getinfos().parameters.len() -
1 /* "this" is also included */ ;
}
if (parametercCount == 1) {
return converter(value);
} else if (parametercCount == 2) {
return converter(value, type);
} else {
throw "Error: converter function must take 1 or 2 parameters"
}
} else if ("number" == type) {
return (value.find(".") == null && value.find("e") == null && value.find("E") == null) ? value.tointeger() : value.tofloat();
} else {
return value;
}
}
}
/**
* JSON Tokenizer
* @package JSONParser
*/
class _JSONTokenizer {
_ptfnRegex = null;
_numberRegex = null;
_stringRegex = null;
_ltrimRegex = null;
_unescapeRegex = null;
constructor() {
// punctuation/true/false/null
this._ptfnRegex = regexp("^(?:\\,|\\:|\\[|\\]|\\{|\\}|true|false|null)");
// numbers
this._numberRegex = regexp("^(?:\\-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?)");
// strings
this._stringRegex = regexp("^(?:\\\"((?:[^\\r\\n\\t\\\\\\\"]|\\\\(?:[\"\\\\\\/trnfb]|u[0-9a-fA-F]{4}))*)\\\")");
// ltrim pattern
this._ltrimRegex = regexp("^[\\s\\t\\n\\r]*");
// string unescaper tokenizer pattern
this._unescapeRegex = regexp("\\\\(?:(?:u\\d{4})|[\\\"\\\\/bfnrt])");
}
/**
* Get next available token
* @param {string} str
* @param {integer} start
* @return {{type,value,length}|null}
*/
function nextToken(str, start = 0) {
local
m,
type,
token,
value,
length,
whitespaces;
// count # of left-side whitespace chars
whitespaces = this._leadingWhitespaces(str, start);
start += whitespaces;
if (m = this._ptfnRegex.capture(str, start)) {
// punctuation/true/false/null
value = str.slice(m[0].begin, m[0].end);
type = "ptfn";
} else if (m = this._numberRegex.capture(str, start)) {
// number
value = str.slice(m[0].begin, m[0].end);
type = "number";
} else if (m = this._stringRegex.capture(str, start)) {
// string
value = str.slice(m[1].begin, m[1].end);
type = "string";
} else {
return null;
}
token = {
type = type,
value = value,
length = m[0].end - m[0].begin + whitespaces
};
return token;
}
/**
* Count # of left-side whitespace chars
* @param {string} str
* @param {integer} start
* @return {integer} number of leading spaces
*/
function _leadingWhitespaces(str, start) {
local r = this._ltrimRegex.capture(str, start);
if (r) {
return r[0].end - r[0].begin;
} else {
return 0;
}
}
// unesacape() replacements table
_unescapeReplacements = {
"b": "\b",
"f": "\f",
"n": "\n",
"r": "\r",
"t": "\t"
};
/**
* Unesacape string escaped per JSON standard
* @param {string} str
* @return {string}
*/
function unescape(str) {
local start = 0;
local res = "";
while (start< str.len()) {
local m = this._unescapeRegex.capture(str, start);
if (m) {
local token = str.slice(m[0].begin, m[0].end);
// append chars before match
local pre = str.slice(start, m[0].begin);
res += pre;
if (token.len() == 6) {
// unicode char in format \uhhhh, where hhhh is hex char code
// todo: convert \uhhhh chars
res += token;
} else {
// escaped char
// @see http://www.json.org/
local char = token.slice(1);
if (char in this._unescapeReplacements) {
res += this._unescapeReplacements[char];
} else {
res += char;
}
}
} else {
// append the rest of the source string
res += str.slice(start);
break;
}
start = m[0].end;
}
return res;
}
}
class JSONEncoder {
static VERSION = "2.0.0";
// max structure depth
// anything above probably has a cyclic ref
static _maxDepth = 32;
/**
* Encode value to JSON
* @param {table|array|*} value
* @returns {string}
*/
function encode(value) {
return this._encode(value);
}
/**
* @param {table|array} val
* @param {integer=0} depth current depth level
* @private
*/
function _encode(val, depth = 0) {
// detect cyclic reference
if (depth > this._maxDepth) {
throw "Possible cyclic reference";
}
local
r = "",
s = "",
i = 0;
switch (typeof val) {
case "table":
case "class":
s = "";
// serialize properties, but not functions
foreach(k, v in val) {
if (typeof v != "function") {
s += ",\"" + k + "\":" + this._encode(v, depth + 1);
}
}
s = s.len() > 0 ? s.slice(1) : s;
r += "{" + s + "}";
break;
case "array":
s = "";
for (i = 0; i< val.len(); i++) {
s += "," + this._encode(val[i], depth + 1);
}
s = (i > 0) ? s.slice(1) : s;
r += "[" + s + "]";
break;
case "integer":
case "float":
case "bool":
r += val;
break;
case "null":
r += "null";
break;
case "instance":
if ("_serializeRaw" in val && typeof val._serializeRaw == "function") {
// include value produced by _serializeRaw()
r += val._serializeRaw().tostring();
} else if ("_serialize" in val && typeof val._serialize == "function") {
// serialize instances by calling _serialize method
r += this._encode(val._serialize(), depth + 1);
} else {
s = "";
try {
// iterate through instances which implement _nexti meta-method
foreach(k, v in val) {
s += ",\"" + k + "\":" + this._encode(v, depth + 1);
}
} catch (e) {
// iterate through instances w/o _nexti
// serialize properties, but not functions
foreach(k, v in val.getclass()) {
if (typeof v != "function") {
s += ",\"" + k + "\":" + this._encode(val[k], depth + 1);
}
}
}
s = s.len() > 0 ? s.slice(1) : s;
r += "{" + s + "}";
}
break;
case "blob":
// This is a workaround for a known bug:
// on device side Blob.tostring() returns null
// (instaead of an empty string)
r += "\"" + (val.len() ? this._escape(val.tostring()) : "") + "\"";
break;
// strings and all other
default:
r += "\"" + this._escape(val.tostring()) + "\"";
break;
}
return r;
}
/**
* Escape strings according to http://www.json.org/ spec
* @param {string} str
*/
function _escape(str) {
local res = "";
for (local i = 0; i< str.len(); i++) {
local ch1 = (str[i] & 0xFF);
if ((ch1 & 0x80) == 0x00) {
// 7-bit Ascii
ch1 = format("%c", ch1);
if (ch1 == "\"") {
res += "\\\"";
} else if (ch1 == "\\") {
res += "\\\\";
} else if (ch1 == "/") {
res += "\\/";
} else if (ch1 == "\b") {
res += "\\b";
} else if (ch1 == "\f") {
res += "\\f";
} else if (ch1 == "\n") {
res += "\\n";
} else if (ch1 == "\r") {
res += "\\r";
} else if (ch1 == "\t") {
res += "\\t";
} else if (ch1 == "\0") {
res += "\\u0000";
} else {
res += ch1;
}
} else {
if ((ch1 & 0xE0) == 0xC0) {
// 110xxxxx = 2-byte unicode
local ch2 = (str[++i] & 0xFF);
res += format("%c%c", ch1, ch2);
} else if ((ch1 & 0xF0) == 0xE0) {
// 1110xxxx = 3-byte unicode
local ch2 = (str[++i] & 0xFF);
local ch3 = (str[++i] & 0xFF);
res += format("%c%c%c", ch1, ch2, ch3);
} else if ((ch1 & 0xF8) == 0xF0) {
// 11110xxx = 4 byte unicode
local ch2 = (str[++i] & 0xFF);
local ch3 = (str[++i] & 0xFF);
local ch4 = (str[++i] & 0xFF);
res += format("%c%c%c%c", ch1, ch2, ch3, ch4);
}
}
}
return res;
}
}
class Json {
function Encode(Table) {
return JSONEncoder.encode(Table);
}
function Decode(Str) {
return JSONParser.parse(Str);
}
}

125
Tool/Math.nut Normal file
View File

@@ -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);
}
}

View File

@@ -4,19 +4,52 @@
创建日期:2025-10-11 11:21 创建日期:2025-10-11 11:21
文件用途:主界面UI 文件用途:主界面UI
*/ */
Actora <- null;
//主界面UI初始化回调 //主界面UI初始化回调
function _MainUI_Enter_() function _MainUI_Enter_(UI_Scene) {
{ if (!_SYS_UI_SCENE_Instance_) _SYS_UI_SCENE_Instance_ = Actor(UI_Scene);
//初始化鼠标
Game_Cursor.GetInstance();
local TestWindow = sq_CreaterWindowInstance("HUD窗口", Window_hud, 0, 0, 1280, 720, 0);
TestWindow.ResetFoucus();
// local Tc = GameWidget_TripleCav("sprite/interface/lenheartwindowcommon.img",175,300);
// _SYS_UI_SCENE_Instance_.AddChild(Tc);
// Tc.SetPos(400,300);
// local NgC = GameWidget_NineGridCav("sprite/interface/lenheartwindowcommon.img", 97, 300, 300);
// _SYS_UI_SCENE_Instance_.AddChild(NgC);
// NgC.SetPos(400, 300);
// local T = sq_GetPng("sprite/item/avatar/swordman/0sm_acap.img",0);
// print(T);
local Test1 = sq_CreaterWindowInstance("测试窗口", Window_NotiBox, 150, 150, 364, 356, 20);
Test1.ResetFoucus();
// local Canv = Canvas(600, 600);
// _SYS_UI_SCENE_Instance_.AddChild(Canv);
// for (local i = 0; i < 10000; i++) {
// Canv.DrawImg("sprite/item/avatar/swordman/0sm_acap.img", 0, i % 600, i / 600 * 28);
// }
} }
//主界面UI事件回调 //主界面UI事件回调
function _MainUI_HandleEvents_(event) function _MainUI_HandleEvents_(EventType, EventData) {
{ _Global_Windows_Events_(EventType, EventData);
if (EventType == UI_EVENT.MOUSEBUTTONDOWN) {
if (Actora) {
_SYS_UI_SCENE_Instance_.RemoveChild(Actora);
Actora = null;
}
}
} }
//主界面UI更新回调 //主界面UI更新回调
function _MainUI_Update_(deltaTime) function _MainUI_Update_(deltaTime) {
{ _Global_Windows_Logic_(deltaTime);
} }
//主界面UI退出回调 //主界面UI退出回调
function _MainUI_Exit_() function _MainUI_Exit_() {}
{
}

63
UI/ObjectClass/Actor.nut Normal file
View File

@@ -0,0 +1,63 @@
/*
文件名:Actor.nut
路径:UI/ObjectClass/Actor.nut
创建日期:2025-10-18 16:33
文件用途:
*/
class Actor extends BaseNode {
function _typeof() {
return "Actor";
}
constructor(obj = null) {
if (obj) {
base.constructor(obj, false);
} else {
base.constructor(sq_CreateActor());
}
}
function AddChild(Act) {
sq_AddChild(this.C_Object, Act.C_Object);
}
function RemoveChild(Act) {
sq_RemoveChild(this.C_Object, Act.C_Object);
}
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]);
}
}
function GetSize(){
}
function SetVisible(Flag) {
sq_SetVisible(this.C_Object, Flag);
}
function GetWorldPos(){
return sq_GetWorldPos(this.C_Object);
}
function SetName(Name) {
sq_SetName(this.C_Object, Name);
}
}

View File

@@ -0,0 +1,17 @@
/*
文件名:BaseNode.nut
路径:UI/ObjectClass/BaseNode.nut
创建日期:2025-10-18 20:43
文件用途:
*/
class BaseNode {
/** @private */
C_Object = null
constructor(CObject, DestructFlag = true) {
this.C_Object = CObject
//析构对象
if (DestructFlag) sq_RegisterDestruction(C_Object, this)
}
}

24
UI/ObjectClass/Canvas.nut Normal file
View File

@@ -0,0 +1,24 @@
/*
文件名:Canvas.nut
路径:UI/ObjectClass/Canvas.nut
创建日期:2025-10-24 22:00
文件用途:画布类
*/
class Canvas extends Actor {
function _typeof() {
return "Canvas";
}
constructor(Width, Height) {
C_Object = sq_CreateCanvas(Width, Height);
sq_RegisterDestruction(C_Object, this);
}
function DrawImg(Img, Index, X, Y) {
sq_Canvas_DrawImg(C_Object, Img, Index, {x = X, y = Y});
}
function DrawImgRect(Img, Index, X, Y, Width, Height) {
sq_Canvas_DrawImgRect(C_Object, Img, Index, {x = X, y = Y,w = Width, h = Height});
}
}

View File

@@ -0,0 +1,80 @@
/*
文件名:GameWidget.nut
路径:UI/ObjectClass/GameWidget.nut
创建日期:2025-10-21 22:05
文件用途:
*/
class GameWidget extends WindowNode {
//组件ID
ObjectId = null;
//本地坐标
Localtion_X = 0;
Localtion_Y = 0;
//是否按下
isLBDown = false;
//是否悬停
isInRect = false;
//点击事件
OnClick = null;
//点击音效
ClickSound = null;
//悬停音效
HoverSound = null;
HoverSoundFlag = false;
constructor(x, y, width, height) {
this.Localtion_X = x;
this.Localtion_Y = y;
this.Width = width;
this.Height = height;
this.X = x;
this.Y = y;
ObjectId = clock();
base.constructor();
SetPos(x, y);
}
function OnMouseEvent(Type, Data, EventInteractiveFlag) {
if (!Visible) return;
//鼠标移动事件
if (Type == UI_EVENT.MOUSEMOTION) {
local Pos = GetWorldPos();
if (Math.IsIntersectRect(Data[0], Data[1], 1, 1, Pos.x, Pos.y, Width, Height)) {
//如果有配置悬停音效
if (HoverSound && !HoverSoundFlag) {
HoverSoundFlag = true;
//TODO 音效系统
// Sq_PlaySoundEffect(HoverSound);
}
isInRect = true;
} else {
HoverSoundFlag = false;
isInRect = false;
}
} else if (Type == UI_EVENT.MOUSEBUTTONDOWN) {
local IMouse = Game_Cursor.GetInstance();
local Pos = GetWorldPos();
if (Math.IsIntersectRect(IMouse.MouseX, IMouse.MouseY, 1, 1, Pos.x, Pos.y, Width, Height)) {
isLBDown = true;
}
} else if (Type == UI_EVENT.MOUSEBUTTONUP) {
local IMouse = Game_Cursor.GetInstance();
local Pos = GetWorldPos();
if (isLBDown && Math.IsIntersectRect(IMouse.MouseX, IMouse.MouseY, 1, 1, Pos.x, Pos.y, Width, Height)) {
if (OnClick) this.OnClick.call(this,this);
if (ClickSound) {
//TODO 音效系统
// Sq_PlaySoundEffect(ClickSound);
}
}
isLBDown = false;
}
foreach (Window in Childrens) {
if (Window instanceof WindowNode) Window.OnMouseEvent(Type, Data);
}
}
}

View File

@@ -0,0 +1,129 @@
/*
文件名:GameWindow.nut
路径:UI/ObjectClass/GameWindow.nut
创建日期:2025-10-18 20:58
文件用途:游戏窗口类
*/
class GameWindow extends WindowNode {
//窗口名称
WindowName = "undefined";
//是否活动窗口Flag
IsActiveFlag = false;
//标题高度
TitleH = null;
//鼠标相对位置
M_Xpos = null;
M_Ypos = null;
//移动Flag
MoveFlag = false;
//是否为独立窗口
IsIndependent = true;
//是否为顶层窗口
IsTop = false;
function _typeof() {
return "GameWindow";
}
constructor(WindowName, gX, gY, gWidth, gHeight, gTitleHeight) {
base.constructor();
//窗口名字
this.WindowName = WindowName;
//宽度
Width = gWidth;
//高度
Height = gHeight;
//标题高度
TitleH = gTitleHeight;
//X坐标
X = gX;
//Y坐标
Y = gY;
SetPos(X, Y);
}
function ResetFoucus() {
SetVisible(true);
//遍历全局窗口数组将自己移除重新添加在末尾
foreach (Index, WindowObj in _SYS_WINDOW_LIST_) {
if (WindowObj.WindowName == this.WindowName) {
_SYS_WINDOW_LIST_.remove(Index);
break;
}
}
_SYS_WINDOW_LIST_.append(this);
SetZOrder(_SYS_WINDOW_LIST_.len());
}
//关闭窗口 -并没有销毁只是隐藏
function CloseWindow() {
this.Visible = false;
}
//销毁全局UI中的窗口 子窗口只要父窗口被销毁就会被销毁
function DestroyWindow() {
this.Visible = false;
this.DestroyFlag = true;
}
function Proc(Dt) {
base.Proc(Dt);
foreach (Window in Childrens) {
if (Window instanceof WindowNode) Window.Proc(Dt);
}
}
//鼠标事件回调
function OnMouseEvent(Type, Data, EventInteractiveFlag) {
if (!Visible) return;
foreach (Window in Childrens) {
if ("OnMouseEvent" in Window) Window.OnMouseEvent(Type, Data,EventInteractiveFlag);
}
//鼠标移动事件
if (Type == UI_EVENT.MOUSEMOTION) {
if (MoveFlag) {
//左键拖动
X = B_X - (M_Xpos - Data[0]);
Y = B_Y - (M_Ypos - Data[1]);
}
}
//鼠标按下事件
else if (Type == UI_EVENT.MOUSEBUTTONDOWN) {
local IMouse = Game_Cursor.GetInstance();
//如果点击事件在窗口内
if (Math.IsIntersectRect(IMouse.MouseX, IMouse.MouseY, 1, 1, X, Y, Width, Height) && !EventInteractiveFlag) {
if (IsIndependent) ResetFoucus();
//如果点下去在标题栏
if (Math.IsIntersectRect(IMouse.MouseX, IMouse.MouseY, 1, 1, X, Y, Width, TitleH)) {
MoveFlag = true;
M_Xpos = IMouse.MouseX; //原始鼠标位置数据
M_Ypos = IMouse.MouseY;
B_X = X; //原始窗口位置
B_Y = Y;
}
}
}
//鼠标弹起事件
else if (Type == UI_EVENT.MOUSEBUTTONUP) {
if (MoveFlag) {
MoveFlag = false;
M_Xpos = null;
M_Ypos = null;
B_X = null;
B_Y = null;
}
}
}
//键盘事件回调
function OnKeyEvent(Type, Data, EventInteractiveFlag) {
if (!Visible) return;
foreach (Window in Childrens) {
if ("OnKeyEvent" in Window) Window.OnKeyEvent(Type, Data);
}
}
}

16
UI/ObjectClass/Sprite.nut Normal file
View File

@@ -0,0 +1,16 @@
/*
文件名:Sprite.nut
路径:UI/ObjectClass/Sprite.nut
创建日期:2025-10-18 19:51
文件用途:精灵类
*/
class Sprite extends Actor {
function _typeof() {
return "Sprite"
}
constructor(ImgPath, Idx) {
C_Object = sq_CreateSprite(ImgPath, Idx);
sq_RegisterDestruction(C_Object,this);
}
}

16
UI/ObjectClass/Text.nut Normal file
View File

@@ -0,0 +1,16 @@
/*
文件名:Text.nut
路径:UI/ObjectClass/Text.nut
创建日期:2025-10-25 15:40
文件用途:
*/
class Text extends Actor {
function _typeof() {
return "Text"
}
constructor(Str, FontIndex,Color) {
C_Object = sq_CreateText(Str, FontIndex, Color);
sq_RegisterDestruction(C_Object,this);
}
}

View File

@@ -0,0 +1,126 @@
/*
文件名:WindowNode.nut
路径:UI/ObjectClass/WindowNode.nut
创建日期:2025-10-18 20:54
文件用途:窗口节点类
*/
_SYS_UI_SCENE_Instance_ <- null;
_SYS_WINDOW_LIST_ <- [];
class WindowNode extends Actor {
//演出状态
PerformanceState = false;
//子控件
Childrens = null;
//刷新函数
UpdateFunc = null;
//是否可见
Visible = true;
//宽度
Width = null;
//高度
Height = null;
//销毁Flag
DestroyFlag = false;
//X坐标
X = null;
B_X = null;
//Y坐标
Y = null;
B_Y = null;
function _typeof() {
return "WindowNode";
}
constructor() {
base.constructor();
//子控件list初始化
Childrens = [];
}
function SetVisible(Flag) {
Visible = Flag;
base.SetVisible(Flag);
}
function AddChild(Act) {
base.AddChild(Act);
Childrens.push(Act);
}
function Proc(Dt){
if (UpdateFunc != null) this.UpdateFunc(Dt);
SetPos(X, Y);
}
}
/**
*
* @function
* @param {any} WindowName
* @param {GameWindow} WindowClass
* @returns {any}
*/
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, gX, gY, gWidth, gHeight, gTitleHeight);
getroottable()._SYS_WINDOW_LIST_.push(NewWindow);
return NewWindow;
}
/**
*
* @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];
//如果窗口不可见并且 处于演出状态
if (!Window.Visible && Window.PerformanceState) {
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);
Window.PerformanceState = true;
}
//无论窗口是否显示都需要调用Proc
Window.Proc(Dt);
}
}
}
function _Global_Windows_Events_(EventType, EventData) {
//先传递鼠标事件
local IMouse = Game_Cursor.GetInstance();
IMouse.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, EventInteractiveFlag);
} else if (EventType == UI_EVENT.KEYDOWN || EventType == UI_EVENT.KEYUP) {
Window.OnKeyEvent(EventType, EventData, EventInteractiveFlag);
}
if (Math.IsIntersectRect(IMouse.MouseX, IMouse.MouseY, 1, 1, Window.X, Window.Y, Window.Width, Window.Height)) {
EventInteractiveFlag = Window;
}
}
}
}

View File

@@ -0,0 +1,34 @@
/*
文件名: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);
}
/**
* 鼠标事件重载函数
* @function override
* @param {any} Type
* @param {any} Data
* @param {boolean} EventInteractiveFlag
* @returns {void}
*/
function OnMouseEvent(Type, Data, EventInteractiveFlag) {
base.OnMouseEvent(Type, Data, EventInteractiveFlag)
if(Type == UI_EVENT.MOUSEBUTTONDOWN) {
}
}
}

View File

@@ -0,0 +1,81 @@
/*
文件名:Cursor.nut
路径:UI/Windows/System/Cursor.nut
创建日期:2025-10-21 18:46
文件用途:
*/
class Game_Cursor extends GameWindow {
//鼠标精灵数组
MouseSprite = null;
//当前鼠标工作ID
CurrentMouseTaskId = 0;
//鼠标X坐标
MouseX = -100;
//鼠标Y坐标
MouseY = -100;
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
* @param {any} EventType
* @param {any} EventData
* @returns {void}
*/
function Event(EventType, EventData) {
if (EventType == UI_EVENT.MOUSEMOTION) {
MouseX = EventData[0];
MouseY = EventData[1];
MouseSprite[CurrentMouseTaskId].SetPos(MouseX, MouseY);
}
}
}

View File

@@ -0,0 +1,38 @@
/*
文件名:NotiBox.nut
路径:UI/Windows/System/NotiBox.nut
创建日期:2025-10-21 21:50
文件用途:
*/
class Window_NotiBox extends GameWindow {
testvalue = 666;
constructor(Name, gX, gY, gWidth, gHeight, gTitleHeight) {
base.constructor(Name, gX, gY, gWidth, gHeight, gTitleHeight);
InitSprite();
// InitButton();
}
function InitSprite() {
local Sp = Sprite("sprite/hud/newantonui.img", 0);
AddChild(Sp);
local Textobj = Text("测试文本",0,sq_RGBA(255,255,255,255));
AddChild(Textobj);
local Textobj2 = Text("测试文本",1,sq_RGBA(255,255,255,255));
Textobj2.SetPos(0,50);
AddChild(Textobj2);
}
function InitButton() {
local Btn = GameWidget_BaseButton(40, 40, 56, 24, "sprite/interface/lenheartwindowcommon.img", 12);
Btn.OnClick = function(btn){
// print(testvalue);
print(this);
print(btn);
}.bindenv(this);
AddChild(Btn);
}
}

View File

@@ -0,0 +1,78 @@
/*
文件名:BaseWidget.nut
路径:UI/Windows/Widget/BaseWidget.nut
创建日期:2025-10-21 22:29
文件用途:基础控件
*/
class GameWidget_BaseButton extends GameWidget {
//按钮状态
ButtonState = 0;
//Img路径
Path = null;
//Img索引
Idx = null;
//帧集合
FrameList = null;
//精灵状态
SpriteState = -1;
//按下时的模拟偏移
DownSimulateOffset = true;
constructor(X, Y, W, H, Path, Idx) {
this.Path = Path;
this.Idx = Idx;
base.constructor(X, Y, W, H);
FrameList = [];
//构造4个精灵
for (local i = 0; i < 4; i++) {
local Buffer = Sprite(this.Path, this.Idx + i);
Buffer.SetVisible(false);
FrameList.push(Buffer);
AddChild(Buffer);
}
}
function ChangeFrame() {
//状态更改 刷新精灵帧
if (ButtonState != SpriteState) {
//按下时模拟偏移的Flag 如果按下 调整Y坐标向下一个单位
if (DownSimulateOffset) {
if (ButtonState == 2) {
Y += 1;
SetPos(X, Y);
} else if (SpriteState == 2) {
Y -= 1;
SetPos(X, Y);
}
}
if (SpriteState != -1) FrameList[SpriteState].SetVisible(false);
SpriteState = ButtonState;
FrameList[SpriteState].SetVisible(true);
}
}
function Proc(Dt) {
//不可用
if (ButtonState == 3) {
} else {
//按下
if (isLBDown) {
ButtonState = 2;
}
//悬停
else if (isInRect) {
ButtonState = 1;
}
//普通
else {
ButtonState = 0;
}
}
ChangeFrame();
}
}

View File

@@ -0,0 +1,63 @@
/*
文件名:NineGridCav.nut
路径:UI/Windows/Widget/NineGridCav.nut
创建日期:2025-10-25 00:35
文件用途:九宫格画布
*/
class GameWidget_NineGridCav extends Canvas {
/**
*
* @function
* @param {string} ImgPath Img路径
* @param {integer} ImgStart Img起始索引
* @param {integer} Width 总宽度
* @param {integer} Height 总高度
* @returns {gamewidget_ninegridcav}
*/
constructor(ImgPath, ImgStart, Width, Height) {
//获取九宫格各部分原始尺寸
local topLeft = sq_GetPng(ImgPath, ImgStart);
local topMid = sq_GetPng(ImgPath, ImgStart + 1);
local topRight = sq_GetPng(ImgPath, ImgStart + 2);
local midLeft = sq_GetPng(ImgPath, ImgStart + 3);
local midMid = sq_GetPng(ImgPath, ImgStart + 4);
local midRight = sq_GetPng(ImgPath, ImgStart + 5);
local bottomLeft = sq_GetPng(ImgPath, ImgStart + 6);
local bottomMid = sq_GetPng(ImgPath, ImgStart + 7);
local bottomRight = sq_GetPng(ImgPath, ImgStart + 8);
//初始化画布尺寸
base.constructor(Width, Height);
//计算中间拉伸区域尺寸
local midWidth = Width - topLeft.Width - topRight.Width;
local midHeight = Height - topLeft.Height - bottomLeft.Height;
//绘制左上角
DrawImg(ImgPath, ImgStart, 0, 0);
//绘制上中(横向拉伸)
DrawImgRect(ImgPath, ImgStart + 1, topLeft.Width, 0, midWidth, topMid.Height);
//绘制右上角
DrawImg(ImgPath, ImgStart + 2, Width - topRight.Width, 0);
//绘制左中(纵向拉伸)
DrawImgRect(ImgPath, ImgStart + 3, 0, topLeft.Height, midLeft.Width, midHeight);
//绘制中间(双向拉伸)
DrawImgRect(ImgPath, ImgStart + 4, topLeft.Width, topLeft.Height, midWidth, midHeight);
//绘制右中(纵向拉伸)
DrawImgRect(ImgPath, ImgStart + 5, Width - midRight.Width, topLeft.Height, midRight.Width, midHeight);
//绘制左下角
DrawImg(ImgPath, ImgStart + 6, 0, Height - bottomLeft.Height);
//绘制下中(横向拉伸)
DrawImgRect(ImgPath, ImgStart + 7, topLeft.Width, Height - bottomMid.Height, midWidth, bottomMid.Height);
//绘制右下角
DrawImg(ImgPath, ImgStart + 8, Width - bottomRight.Width, Height - bottomRight.Height);
}
}

View File

@@ -0,0 +1,30 @@
/*
文件名:TripleCav.nut
路径:UI/Windows/Widget/TripleCav.nut
创建日期:2025-10-24 23:15
文件用途:三联画布
*/
class GameWidget_TripleCav extends Canvas {
/**
* 创建三联图画布
* @function
* @param {string} ImgPath Img路径
* @param {integer} ImgStart Img起始索引
* @param {integer} Width 总宽度
* @returns {gamewidget_triplecav}
*/
constructor(ImgPath, ImgStart, Width) {
local Left_Width = sq_GetPng(ImgPath, ImgStart).Width;
local Height = sq_GetPng(ImgPath, ImgStart).Height;
local Right_Width = sq_GetPng(ImgPath, ImgStart + 2).Width;
base.constructor(Width, Height);
//绘制左侧
DrawImg(ImgPath, ImgStart, 0, 0);
//绘制中间
DrawImgRect(ImgPath, ImgStart + 1, Left_Width, 0, Width - Left_Width - Right_Width, Height);
//绘制右侧
DrawImg(ImgPath, ImgStart + 2, Width - Right_Width, 0);
}
}

View File

@@ -6,22 +6,31 @@
*/ */
enum CHARACTERJOB { enum CHARACTERJOB {
SWORDMAN // 男鬼剑士 SWORDMAN, // 男鬼剑士
FIGHTER // 女格斗家 FIGHTER, // 女格斗家
GUNNER // 男神枪手 GUNNER, // 男神枪手
MAGE // 女魔法师 MAGE, // 女魔法师
PRIEST // 男圣职者 PRIEST, // 男圣职者
AT_GUNNER // 女神枪手 AT_GUNNER, // 女神枪手
THIEF // 暗夜使者 THIEF, // 暗夜使者
AT_FIGHTER // 男格斗家 AT_FIGHTER, // 男格斗家
AT_MAGE // 男魔法师 AT_MAGE, // 男魔法师
DEMONIC_SWORDMAN // 黑暗武士 DEMONIC_SWORDMAN, // 黑暗武士
CREATOR_MAGE // 缔造者 CREATOR_MAGE, // 缔造者
AT_SWORDMAN // 女鬼剑士 AT_SWORDMAN, // 女鬼剑士
KNIGHT // 守护者 KNIGHT, // 守护者
DEMONIC_LANCER // 魔枪士 DEMONIC_LANCER, // 魔枪士
AT_PRIEST // 女圣职者 AT_PRIEST, // 女圣职者
GUN_BLADER // 枪剑士 GUN_BLADER, // 枪剑士
ARCHER // 弓箭手 ARCHER, // 弓箭手
MAX // 无 MAX // 无
}; }
enum UI_EVENT {
MOUSEMOTION, //鼠标移动
MOUSEBUTTONDOWN, //鼠标按下
MOUSEBUTTONUP, //鼠标释放
MOUSEWHEEL //鼠标滚轮
KEYDOWN //键盘按下
KEYUP //键盘释放
}

View File

@@ -31,5 +31,62 @@
}, },
"UI/MainUI.nut": { "UI/MainUI.nut": {
"description": "UI入口" "description": "UI入口"
},
"UI/ObjectClass": {
"description": "对象类"
},
"UI/ObjectClass/Actor.nut": {
"description": "演员类"
},
"UI/ObjectClass/Sprite.nut": {
"description": "精灵类"
},
"UI/ObjectClass/BaseNode.nut": {
"description": "基础节点"
},
"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": "鼠标"
},
"UI/Windows/Widget": {
"description": "控件"
},
"UI/Windows/Widget/BaseWidget.nut": {
"description": "基础控件"
},
"UI/ObjectClass/GameWidget.nut": {
"description": "游戏_控件类"
},
"UI/ObjectClass/GameWindow.nut": {
"description": "游戏_窗口类"
},
"UI/ObjectClass/Canvas.nut": {
"description": "画布类"
},
"UI/Windows/Widget/TripleCav.nut": {
"description": "三联图画布"
},
"UI/Windows/Widget/NineGridCav.nut": {
"description": "九宫格画布"
},
"UI/ObjectClass/Text.nut": {
"description": "文本类"
} }
} }

View File

@@ -2,7 +2,7 @@
* *
* @function * @function
* @param {any} C_Object * @param {any} C_Object
* @param {integer} state * @param {integer} state 状态编号
* @returns {void} * @returns {void}
*/ */
function sq_SetState(C_Object, state) {} function sq_SetState(C_Object, state) {}
@@ -11,8 +11,7 @@ function sq_SetState(C_Object, state) {}
* *
* @function * @function
* @param {any} C_Object * @param {any} C_Object
* @param {any} key * @param {string} key 动作名称
*
* @returns {void} * @returns {void}
*/ */
function sq_SetAction(C_Object, key) {} function sq_SetAction(C_Object, key) {}
@@ -59,8 +58,8 @@ function sq_SetPosition(C_Object, x, y, z) {}
* *
* @function * @function
* @param {any} C_Object * @param {any} C_Object
* @param {string} Name * @param {string} Name 储存器名称
* @param {any} Type * @param {string} Type 数据类型(int,float,string,bool)
* @returns {void} * @returns {void}
*/ */
function sq_GetVars(C_Object, Name, Type) {} function sq_GetVars(C_Object, Name, Type) {}
@@ -69,8 +68,8 @@ function sq_GetVars(C_Object, Name, Type) {}
* *
* @function * @function
* @param {any} C_Object * @param {any} C_Object
* @param {string} Name * @param {string} Name 储存器名称
* @param {any} Type * @param {string} Type 数据类型(int,float,string,bool)
* @param {any} Value * @param {any} Value
* @returns {void} * @returns {void}
*/ */
@@ -82,14 +81,44 @@ function sq_SetVars(C_Object, Name, Type, Value) {}
* @param {any} C_Object * @param {any} C_Object
* @returns {void} * @returns {void}
*/ */
function sq_GetDirection(C_Object) { function sq_GetDirection(C_Object) {}
}
/** /**
* *
* @function * @function
* @param {any} C_Object * @param {any} C_Object
* @param {integer} Dir * @param {integer} Dir 方向(0左 1右)
* @returns {void} * @returns {void}
*/ */
function sq_SetDirection(C_Object, Dir) {} function sq_SetDirection(C_Object, Dir) {}
function sq_CreateActor() {}
function sq_RegisterDestruction(a,b) {}
function sq_CreateSprite(a,b) {}
function sq_CreateCanvas(a,b) {}
function sq_CreateText(a,b,c) {}
function sq_AddChild(a,b){}
function sq_RemoveChild(a,b){}
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){}
function sq_GetWorldPos(a){}
function sq_SetVisible(a,b){}
function sq_SetName(a,b){}
function sq_Canvas_DrawImg(a,b,c,d){}
function sq_Canvas_DrawImgRect(a,b,c,d){}
function sq_GetImg(a){}
function sq_GetPng(a,b){}
function sq_OutPutTable(...){}
function output(...){}

View File

@@ -1,4 +1,15 @@
function _InitFont_() {
return [
{ path = "Fonts/VonwaonBitmap-12px.ttf", size = 12 },
{ path = "Fonts/VonwaonBitmap-12px.ttf", size = 24 },
{ path = "Fonts/NotoSansSC-Light.otf", size = 12 }
];
}
function main() { function main() {
//初始化随机数种子
srand(time());
local SM = StateMachine.GetInstance(); local SM = StateMachine.GetInstance();
SM.RegisterState(CHARACTERJOB.SWORDMAN, "Character_Rest", 0); SM.RegisterState(CHARACTERJOB.SWORDMAN, "Character_Rest", 0);