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
707 lines
26 KiB
TypeScript
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);
|
|
}
|
|
}
|