Files
ZhouXiao 487c68994d feat: add builder configuration file
feat: add cocos-service configuration file
feat: add device configuration file
feat: add engine configuration file
feat: add information configuration file
feat: add program configuration file
feat: add project configuration file
feat: add TypeScript configuration file
2025-12-22 11:42:51 +08:00

707 lines
26 KiB
TypeScript

import { SpriteFrame, Vec3, Node, Vec2, Button, v2, sys, instantiate, game, Game, v3, Sprite, misc, UITransform, Layers, Camera, Canvas, director, Director, ImageAsset, renderer, RenderTexture, Size, Texture2D, view, sp } from "cc";
import { PlatformManager } from "../manager/PlatformManager";
import { ResModel } from "../model/ResModel";
import { LoadTools } from "./LoadTools";
import { AStar } from "./AStar";
import { BFSPathfinding } from "./BFS";
import { SplitRenderHelper } from "../SplitRender/SplitRenderHelper";
export type index = {
x: number;
y: number;
}
//@ts-ignore
game._calculateDT = function _calculateDT(useFixedDeltaTime: boolean): number {
this._useFixedDeltaTime = useFixedDeltaTime;
if (useFixedDeltaTime) {
this._startTime = performance.now();
return this.frameTime / 1000;
}
const now = performance.now();
this._deltaTime = now > this._startTime ? (now - this._startTime) / 1000 : 0;
if (this._deltaTime > Game.DEBUG_DT_THRESHOLD) {
this._deltaTime = this.frameTime / 1000;
}
this._startTime = now;
return this._deltaTime * Tools.getTimeScale();
}
/** 游戏常用工具类 */
export class Tools {
private static timeScale = 1;
private static aStar: AStar = new AStar();
private static bfs: BFSPathfinding = new BFSPathfinding();
/**
* 使用A*算法进行搜索。
* @param map 二维数字数组,代表地图或其他需要搜索的结构。
* @param start 搜索的起始点,其格式为 index 类型。
* @param end 搜索的终点,其格式为 index 类型。
* @param type 搜索类型,用数字表示,默认为 0。不同的类型可能影响搜索算法的行为。
* @returns 返回搜索结果,通常是一个路径数组或者搜索到的目标。
*/
public static aStarSearch(map: number[][], start: index, end: index, type: number = 0) {
this.aStar.setMap(map);
return this.aStar.search(start, end, type);
}
public static setaStarValue(startValue: number, endValue: number, pathValue: number) {
this.aStar.setValue(startValue, endValue, pathValue);
}
public static setaStarEightDirections(isEightDirections: boolean) {
this.aStar.setEightDirections(isEightDirections);
}
public static setaStarWeightMap(weightMap: number[][]) {
this.aStar.setWeightMap(weightMap);
}
public static setaStarNeighborMap(neighborMap: Map<index, index[]>) {
this.aStar.setNeighborMap(neighborMap);
}
/**
* 使用广度优先搜索算法在地图上寻找从起点到终点的路径。
* @param map 二维数字数组表示的地图。
* @param start 起点的索引。
* @param end 终点的索引。
* @returns 返回一个路径数组,如果不存在路径则返回空数组。
*/
public static bfsSearch(map: number[][], start: index, end: index) {
this.bfs.setMap(map); // 设置广度优先搜索对象的地图
return this.bfs.findPath(start, end); // 执行搜索并返回路径
}
/**
* 存储本地数据
* @param {*} isObject 是否是一个对象或者数组
*/
public static setStorage(key: string, value: any, isObject = false) {
PlatformManager.setStorage(key, value, isObject);
}
/**
* 获取存储数据
* @param {*} isObject 是否是一个对象或者数组
*/
public static getStorage(key: string, isObject = false) {
return PlatformManager.getStorage(key, isObject);
};
/**
* 获取时间缩放
* @returns 时间缩放
*/
public static getTimeScale() {
return Tools.timeScale;
}
/**
* 设置时间缩放
* @param scale 时间缩放
*/
public static setTimeScale(scale: number) {
Tools.timeScale = scale;
}
/**
* 获取截图
* @param node 截图的节点
* @param parent 截图的父节点
* @param pos 截图的位置
* @param canvas 默认摄像机渲染的canvas
* @param normalCamera 默认摄像机
*/
public static getScreenShot(node: Node, parent: Node, pos: Vec3, canvas: Canvas, normalCamera: Camera) {
const newCamera = new Node("PhotoCamera");
newCamera.setParent(canvas.node);
newCamera.setPosition(0, 0, 1000);
newCamera.addComponent(Camera);
newCamera.getComponent(Camera).visibility = normalCamera.visibility;
newCamera.getComponent(Camera).clearFlags = normalCamera.clearFlags;
newCamera.getComponent(Camera).near = normalCamera.near;
newCamera.getComponent(Camera).far = normalCamera.far;
newCamera.getComponent(Camera).projection = renderer.scene.CameraProjection.ORTHO;
newCamera.getComponent(Camera).orthoHeight = normalCamera.orthoHeight;
const newRenderTexture = new RenderTexture();
newRenderTexture.reset({
width: view.getVisibleSize().width,
height: view.getVisibleSize().height
});
newCamera.getComponent(Camera).targetTexture = newRenderTexture;
director.once(Director.EVENT_AFTER_DRAW, () => {
const newSpriteFrame = new SpriteFrame();
let data = newRenderTexture.readPixels(Math.round(node.getWorldPosition().x - node.getComponent(UITransform).width / 2 * node.scale.x),
Math.round(node.getWorldPosition().y - node.getComponent(UITransform).height / 2 * node.scale.y),
node.getComponent(UITransform).width * node.scale.x, node.getComponent(UITransform).height * node.scale.y)
let image = new ImageAsset();
image.reset({
_data: data,
_compressed: false,
width: node.getComponent(UITransform).width * node.scale.x,
height: node.getComponent(UITransform).height * node.scale.y,
format: Texture2D.PixelFormat.RGBA8888
})
let newTexture = new Texture2D();
newTexture.image = image;
newSpriteFrame.texture = newTexture;
newSpriteFrame.packable = false;
if (sys.isNative && (sys.os === sys.OS.IOS || sys.os === sys.OS.OSX)) {
newSpriteFrame.flipUVY = false;
} else {
newSpriteFrame.flipUVY = true;
}
let newSprite = new Node("PhotoSprite");
newSprite.addComponent(Sprite);
newSprite.setParent(parent);
newSprite.setPosition(pos);
newSprite.layer = Layers.Enum.UI_2D;
newSprite.getComponent(UITransform)
.setContentSize(new Size(node.getComponent(UITransform).width,
node.getComponent(UITransform).height));
newSprite.getComponent(Sprite).spriteFrame = newSpriteFrame;
newCamera.getComponent(Camera).targetTexture = null;
})
}
/**
* 保存文件。
* @param textToWrite 要保存的文件内容
* @param fileNameToSaveAs 要保存的文件名
* @param fileType 要保存的文件格式,默认为Json
*/
public static saveForBrowser(textToWrite: any, fileNameToSaveAs: string, fileType: string = 'application/json') {
if (sys.isBrowser) {
console.log("浏览器");
let textFileAsBlob = new Blob([textToWrite], { type: fileType });
let downloadLink = document.createElement("a");
downloadLink.download = fileNameToSaveAs;
downloadLink.innerHTML = "Download File";
downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);
downloadLink.click();
}
}
/**
* 获取spine指定动画时间,如果没有该动画 则返回0
* @param spine 骨骼动画
* @param aniName 动画名称
* @returns 动画时间
*/
public static getSpineAnimationTime(spine: sp.Skeleton, aniName: string) {
const state = spine.getState();
if (state == undefined) throw `[ERROR SPINE ANIMATION] 无法获取获取动画状态`;
const { animations } = state.data.skeletonData;
let result = 0;
for (const key in animations) {
if (Object.prototype.hasOwnProperty.call(animations, key)) {
const element = animations[key];
if (element.name == aniName) {
result = element.duration;
}
}
}
return result;
}
//-----------------------------节点预制体相关-------------------------------
/**
* 新建一个预制体在场景里
* @param preName 预制体名字或url
* @param callFunc 加载预制体 完成后回调
* @param parent 存放预制体的父节点
* @param Pos 预制体的坐标
* @param zIndex 预制体的层级
*/
public static newPrefab(preName: string, parent?: Node, Pos?: Vec3, callFunc?: (age?: Node) => void): Node {
return NodeTools._ins.newPrefab(preName, callFunc, parent, Pos);
}
/**
* 新建一个图片在场景里
* @param sprName 图片名字或url
* @param callFunc 加载预制体 完成后回调
* @param parent 存放预制体的父节点
* @param Pos 预制体的坐标
* @param zIndex 预制体的层级
*/
public static newSprite(sprName: string, parent?: Node, Pos?: Vec3, callFunc?: (age?: Node) => void): Node {
return NodeTools._ins.newSprite(sprName, callFunc, parent, Pos);
}
/**
* 设置一个节点的SpriteFrame
* @param nodeT 节点的Node
* @param sprUrl 图片的url或者存放到resArr的名字
*/
public static setSpriteFrame(nodeT: Node, sprUrl: string) {
NodeTools._ins.setSpriteFrame(nodeT, sprUrl);
}
/** 设置一个节点的 groupIndex 包含子物体 */
public static setNodeLayerIndex(nodeT: Node, layer: Layers.Enum) {
NodeTools._ins.setNodeLayerIndex(nodeT, layer);
}
/**
* 设置一个Button的按下和松开的SpriteFrame
* @param norUrl 默认状态的名字或者路径
* @param preUrl 按下状态的名字或者路径
*/
public static setBtnClickSpr(Btn: Button, norUrl: string, preUrl: string) {
NodeTools._ins.setBtnClickSpr(Btn, norUrl, preUrl);
};
/** 切换父物体 不改变显示位置*/
public static setNodeParent(node: Node, parent: Node) {
NodeTools._ins.setNodeParent(node, parent);
};
//----------------------------------数学数组相关----------------------------------
/**
* 将多维数组展平
* @param arr 需要展平的多维数组
* @returns 展平后的数组
*/
public static flatArray(arr: any[]) {
return arr.reduce((acc, curr) => {
return acc.concat(Array.isArray(curr) ? Tools.flatArray(curr) : curr);
}, []);
}
/**
* 从数组中随机获取元素
* @param arr 需要随机获取元素的数组
* @param num 需要获取的元素数量
* @param sortFunc 排序函数,可选
* @returns 返回随机获取的元素数组
*/
public static randomGetElementFromArray(arr: any[], num: number, sortFunc: (a: any, b: any) => number = null) {
const tempArr = arr.slice();
const resultArr = [];
while (resultArr.length < num) {
const randomIndex = Tools.random(0, tempArr.length - 1);
resultArr.push(tempArr[randomIndex]);
tempArr.splice(randomIndex, 1);
}
if (sortFunc) {
resultArr.sort(sortFunc);
}
return resultArr;
}
/**
* 获取随机数
* @param isInteger 是否随机整数 默认整数
*/
public static random(x1: number, x2: number, isInteger = true): number {
return MathTools._ins.random(x1, x2, isInteger);
}
/**
* 根据概率数组 随机概率 返回数组的index
* @param chooseArr 需要随机概率的数组 例如[0.05,0.1,0.2,0.3]
*/
public static chooseRandom(chooseArr: Array<number>) {
return MathTools._ins.chooseRandom(chooseArr);
}
/** 传入一个弧度 返回一个Y轴折射后的弧度 */
public static refractionY(rad: number) {
return MathTools._ins.refractionY(rad);
};
/** 传入一个弧度 返回一个轴折射后的弧度 */
public static refractionX(rad: number) {
return MathTools._ins.refractionX(rad);
};
/** 重新打乱一个数组的顺序 洗牌 */
public static againSortArr(Arr: Array<any>) {
MathTools._ins.againSortArr(Arr);
};
/**
* 将一个数组 按照里面的对象排序
* @param tempArr 传入的数组
* @param sortName 对象属性名字
* @param isReverse 是否倒序
*/
public static sortArrForObject(tempArr: Array<any>, sortName: string, isReverse = false) {
MathTools._ins.sortArrForObject(tempArr, sortName, isReverse);
};
/**
* 取一定范围内不重复的数字
* @param minNum 最小取值范围
* @param maxNum 最大取值范围
* @param getNum 取几个数字
*/
public static getDiffNumRandom(minNum: number, maxNum: number, getNum: number) {
return MathTools._ins.getDiffNumRandom(minNum, maxNum, getNum);
};
//--------------------------------向量坐标计算相关------------------------------------
/**
* 根据两个点 求角度
* @param pos1 起始点坐标
* @param pos2 结束点坐标
* @param isVertical 是否以竖直方向为0度开始
*/
public static getAngleForPos(pos1: Vec2, pos2: Vec2, isVertical = false): number {
return VecTools._ins.getAngleForPos(pos1, pos2, isVertical);
};
/** 获取两个坐标之间的距离 */
public static getDistance(pos1: Vec3 | Vec2, pos2: Vec3 | Vec2): number {
if (pos1 instanceof Vec2 && pos2 instanceof Vec2) {
return Vec2.distance(pos1, pos2);
}
if (pos1 instanceof Vec3 && pos2 instanceof Vec3) {
return Vec3.distance(pos1, pos2);
}
};
/**
* 根据一个角度和长度 计算相对应的坐标
* @param angle 角度
* @param len 该角度上的长度
* @param startPos 初始的坐标
*/
public static getPosForAngleLen(angle: number, len: number, startPos: Vec2 = v2(0, 0)) {
return VecTools._ins.getPosForAngleLen(angle, len, startPos);
}
/**
* 获取节点在另一个节点下的坐标
* @param obj 节点
* @param mainObj 相对于的另一个节点
*/
public static getToNodePosForNode(obj: Node, mainObj: Node): Vec2 {
return VecTools._ins.getToNodePosForNode(obj, mainObj);
};
/** 获取节点的世界坐标 */
public static getToWorldPosAR(obj: Node) {
return VecTools._ins.getToWorldPosAR(obj);
}
/**
* 通过世界坐标 获取相对节点的坐标
* @param worldPos 世界坐标
* @param obj 相对节点下的
*/
public static getToNodePosForWorld(worldPos: Vec3, obj: Node) {
return VecTools._ins.getToNodePosForWorld(worldPos, obj);
}
/** 二维向量转三维向量 */
public static getVec3ForVec2(vec2: Vec2) {
return VecTools._ins.getVec3ForVec2(vec2);
}
/** 三维向量转二维向量 */
public static getVec2ForVec3(vec3: Vec3) {
return VecTools._ins.getVec2ForVec3(vec3);
}
/** 获取两向量方向 */
public static getDirection(startPos: Vec3 | Vec2, endPos: Vec3 | Vec2) {
return VecTools._ins.getDirection(startPos, endPos);
}
/** 获取多边形面积 */
public static getPolygonArea(polygon: Vec2[]) {
return VecTools._ins.getPolygonArea(polygon);
}
//--------------------------------数组操作相关------------------------------------
/** 根据value值 从数组里面移除 */
public static removeArrForValue(tempArr: Array<any>, value: any) {
return tempArr.splice(tempArr.indexOf(value), 1);
}
/** 从数组里面添加一个该数组里没有的元素 */
public static addArrNoValue(tempArr: Array<any>, value: any) {
if (tempArr.indexOf(value) < 0) {
tempArr.push(value);
return true;
}
return false;
}
/** 从数组指定位置 插入某个元素 */
public static addArrIndex(tempArr: Array<any>, index: number, value: any) {
return tempArr.splice(index, 0, value);
}
//--------------------------------其他------------------------------------
/**
* 字符串指定位置插入新字符
* @param source 需要操作的字符串
* @param start 从那个位置开始插入
* @param newStr 插入的新的字符
*/
public static insertStrForIndex(source: string, start: number, newStr: string): string {
return source.slice(0, start) + newStr + source.slice(start);
};
/**
* 数字整数前边补零 并返回字符串
* @param num 传入的数字
* @param length 前边补几个零
*/
public static prefixInteger(num: number, length = 2): string {
return (Array(length).join('0') + num).slice(-length);
};
/** 获取系统语言 */
public static getLanguageType(): string {
var langNumType = "EN"; //默认英语
if (sys.language == sys.Language.CHINESE) {
if (sys.languageCode.toLowerCase().indexOf("zh-cn") != -1 ||
sys.languageCode.toLowerCase().indexOf("zh_cn") != -1 ||
sys.languageCode.toLowerCase().indexOf("zh-hans-cn") != -1) {
langNumType = "CN"; //简体
} else {
langNumType = "CHT"; //繁体
}
}
// else if ( sys.language == sys.Language.KOREAN ) {
// langNumType = "KOR"; //韩语
// }
// else if (sys.language == sys.Language.JAPANESE) {
// langNumType = "JP"; //日语
// }
// else if ( window.navigator.language == "th-TH" ) {
// langNumType = "TH"; //泰语
// }
return langNumType;
}
}
/** 节点相关 工具类 */
class NodeTools {
/** 单例模式 */
private static _instance: NodeTools = new NodeTools();
private constructor() { }
public static get _ins() {
return this._instance;
}
/** 新建一个预制体在场景里 */
public newPrefab(preName: string, callFunc?: (age?: Node) => void, parent?: Node, Pos?: Vec3): Node {
let prefab = ResModel._ins.PrefabDic.get(preName);
let clone: Node = null;
if (prefab != null) {
clone = instantiate(prefab);
if (parent) { parent.addChild(clone) };
if (Pos) { clone.position = v3(Pos.x, Pos.y, Pos.z) };
if (callFunc != null) {
callFunc(clone);
}
} else {
LoadTools._ins.loadResPrefab(preName, callFunc, parent, Pos);
}
return clone;
}
/** 新建一个图片在场景里 */
public newSprite(sprName: string, callFunc?: (age?: Node) => void, parent?: Node, Pos?: Vec3) {
let sprite = new Node();
sprite.name = sprName;
sprite.layer = Layers.Enum.UI_2D;
if (ResModel._ins.SpriteFrameDic.get(sprName) != null) {
sprite.addComponent(Sprite).spriteFrame = ResModel._ins.SpriteFrameDic.get(sprName);
if (parent) { parent.addChild(sprite) };
if (Pos) { sprite.position = v3(Pos.x, Pos.y, Pos.z) };
if (callFunc != null) {
callFunc(sprite);
}
} else {
sprite.addComponent(Sprite);
LoadTools._ins.loadResSpriteFrame(sprName, sprite, parent, Pos, callFunc);
}
return sprite;
}
/** 设置一个节点的SpriteFrame */
public setSpriteFrame(nodeT: Node, sprUrl: string) {
if (nodeT.getComponent(Sprite) == null) {
nodeT.addComponent(Sprite);
}
if (ResModel._ins.SpriteFrameDic.get(sprUrl)) {
nodeT.getComponent(Sprite).spriteFrame = ResModel._ins.SpriteFrameDic.get(sprUrl)
} else {
LoadTools._ins.loadResAny(sprUrl, SpriteFrame, (spriteFrame: SpriteFrame) => {
nodeT.getComponent(Sprite).spriteFrame = spriteFrame;
})
}
}
/** 设置一个节点的 所属层 包含子物体 */
public setNodeLayerIndex(nodeT: Node, layer: Layers.Enum) {
nodeT.layer = layer;
for (let i = 0; i < nodeT.children.length; i++) {
this.setNodeLayerIndex(nodeT.children[i], layer);
}
}
/** 设置一个Button的按下和松开的SpriteFrame */
public setBtnClickSpr(Btn: Button, norUrl: string, preUrl: string) {
if (ResModel._ins.SpriteFrameDic.get(norUrl)) {
Btn.getComponent(Button).normalSprite = ResModel._ins.SpriteFrameDic.get(norUrl)
Btn.getComponent(Button).hoverSprite = ResModel._ins.SpriteFrameDic.get(norUrl)
Btn.getComponent(Button).pressedSprite = ResModel._ins.SpriteFrameDic.get(preUrl)
} else {
LoadTools._ins.loadResAny(norUrl, SpriteFrame, (spr: SpriteFrame) => {
Btn.getComponent(Button).normalSprite = spr;
Btn.getComponent(Button).hoverSprite = spr;
});
LoadTools._ins.loadResAny(preUrl, SpriteFrame, (spr: SpriteFrame) => {
Btn.getComponent(Button).pressedSprite = spr;
});
}
};
/** 切换父物体 不改变坐标 */
public setNodeParent(node: Node, parent: Node) {
let Pos = VecTools._ins.getToNodePosForNode(node, parent);
node.parent = parent;
node.position = v3(Pos.x, Pos.y);
};
}
/** 数学数组计算相关 工具类 */
class MathTools {
/** 单例模式 */
private static _instance: MathTools = new MathTools();
private constructor() { }
public static get _ins() {
return this._instance;
}
/** 获取随机数 */
public random(x1: number, x2: number, isInteger = true): number {
if (isInteger) {
return x1 + Math.floor(Math.random() * (x2 - x1 + 1));
}
return Math.random() * (x2 - x1) + x1;
}
/** 根据概率数组 随机概率 返回数组的index */
public chooseRandom(chooseArr: Array<number>) {
let total = 0; //概率总值
//首先计算出概率的总值,用来计算随机范围
for (let i = 0; i < chooseArr.length; i++) {
total += chooseArr[i];
}
let randNum = this.random(0, total, false)
for (let i = 0; i < chooseArr.length; i++) {
if (randNum < chooseArr[i] && chooseArr[i] > 0) {
return i;
} else {
randNum -= chooseArr[i];
}
}
return chooseArr.length - 1;
}
/** 弧度折射Y轴 */
public refractionY(rad: number) {
return Math.atan2(Math.sin(rad), -Math.cos(rad));
};
/** 弧度折射X轴 */
public refractionX(rad: number) {
return Math.atan2(-Math.sin(rad), Math.cos(rad));
};
/** 重新洗牌 一个数组 */
public againSortArr(Arr: Array<any>) {
for (let i = 0; i < Arr.length; i++) {
let tempR = Tools.random(0, Arr.length - 1);
if (tempR != i) {
let temp = Arr[i];
Arr[i] = Arr[tempR];
Arr[tempR] = temp;
}
}
}
/** 数组 对象排序 对象属性 是否倒序 */
public sortArrForObject(tempArr: Array<any>, sortName: string, isReverse = false) {
if (!isReverse) {
tempArr.sort((a, b) => {
return a[sortName] - b[sortName];
});
} else {
tempArr.sort((a, b) => {
return b[sortName] - a[sortName];
});
}
};
/** 取一定范围内不重复的数字 */
public getDiffNumRandom(minNum: number, maxNum: number, getNum: number) {
var arr = [];
for (let i = minNum; i <= maxNum; i++) {
arr.push(i);
}
const tempLen = arr.length - getNum;
for (let i = 0; i < tempLen; i++) {
let tempI = Tools.random(0, arr.length - 1);
arr.splice(tempI, 1);
}
return arr;
};
}
/** 向量坐标转换相关工具类 */
class VecTools {
/** 单例模式 */
private static _instance: VecTools = new VecTools();
private constructor() { }
public static get _ins() {
return this._instance;
}
/** 根据两个点 求角度 */
public getAngleForPos(pos1: Vec2, pos2: Vec2, isVertical = false): number {
let rad = 0;
if (isVertical) {
rad = -Math.atan2(pos2.x - pos1.x, pos2.y - pos1.y);
} else {
rad = Math.atan2(pos2.y - pos1.y, pos2.x - pos1.x);
}
return misc.radiansToDegrees(rad);
}
/** 根据一个角度和长度 计算相对应的坐标 */
public getPosForAngleLen(angle: number, len: number, startPos: Vec2 = v2(0, 0)) {
let rad = misc.degreesToRadians(angle);
return v2(startPos.x + Math.cos(rad) * len, startPos.y + Math.sin(rad) * len);
}
/** 获取节点在另一个节点下的坐标 */
public getToNodePosForNode(obj: Node, mainObj: Node): Vec2 {
let worldPos = obj.parent.getComponent(UITransform).convertToWorldSpaceAR(obj.position);
let nodePos = mainObj.getComponent(UITransform).convertToNodeSpaceAR(worldPos)
return v2(nodePos.x, nodePos.y);
};
/** 获取节点的世界坐标 */
public getToWorldPosAR(obj: Node) {
return obj.parent.getComponent(UITransform).convertToWorldSpaceAR(obj.position);
}
/** 通过世界坐标 获取相对节点的坐标 */
public getToNodePosForWorld(worldPos: Vec3, obj: Node) {
return obj.getComponent(UITransform).convertToNodeSpaceAR(worldPos);
}
/** 二维向量转三维向量 */
public getVec3ForVec2(vec2: Vec2) {
return v3(vec2.x, vec2.y, 0);
}
/** 三维向量转二维向量 */
public getVec2ForVec3(vec3: Vec3) {
return v2(vec3.x, vec3.y);
}
/** 获取两向量方向和距离
* @param startPos 起始位置
* @param endPos 结束位置
*/
public getDirection(startPos: Vec3 | Vec2, endPos: Vec3 | Vec2) {
if (startPos instanceof Vec2 && endPos instanceof Vec2) {
const deltaPos = endPos.clone().subtract(startPos);
const direction = deltaPos.normalize();
return direction;
} else if (startPos instanceof Vec3 && endPos instanceof Vec3) {
const deltaPos = endPos.clone().subtract(startPos);
const direction = deltaPos.normalize();
return direction;
}
}
public getPolygonArea(polygon: Vec2[]) {
return SplitRenderHelper.calculatePolygonArea(polygon);
}
}