import Vector4 = Laya.Vector4;
import Vector2 = Laya.Vector2;
import Camera = Laya.Camera;
import Vector3 = Laya.Vector3;
import Point = Laya.Point;
export default class MathE {
/**
* 取 [ min , max ) 范围的随机数
* @param min
* @param max
* @param isInt
*/
public static range(min: number, max: number, isInt: boolean = false): number {
if (max < min) {
console.error(`[MathE].range(): 错误的输入! [${min},${max})`);
return null;
}
if (!isInt) {
return (min + (max - min) * Math.random());
} else {
return Math.floor(min + (max - min) * Math.random());
}
}
/**
* 从一个数组里面随机取一些值[min, max)
* @param min 范围区间
* @param max 范围区间
* @param n 取多少
*/
public static randomArray(min: number, max: number, n: number): Array<number> {
if (max < min || n <= 0 || n > max - min) {
console.error(`[MathE].randomArray(): 错误的输入! [${min},${max}], 数量 ${n}`);
return null;
}
let arr: Array<number> = new Array<number>();
let result: Array<number> = new Array<number>();
for (let i = min; i < max; i++) {
arr.push(i);
}
for (let j = 0; j < n; j++) {
let r: number = MathE.range(0, arr.length, true);
result.push(arr[r]);
arr.splice(r, 1);
}
return result;
}
/**
* 从p1到p2的方向单位向量
* @param p1
* @param p2
*/
public static normalizeM2(p1: { r: number, c: number } | any, p2: { r: number, c: number } | any): { x: number, y: number } {
let x = p2.c - p1.c;
let y = p2.r - p1.r;
var d = Math.sqrt(x * x + y * y);
if (d > 0) {
var id = 1.0 / d;
x *= id;
y *= id;
}
return { x: x, y: y }
}
/**
* 从p1到p2的方向单位向量
* @param p1
* @param p2
*/
public static normalize(p1: { x: number, y: number } | any, p2: { x: number, y: number } | any): { x: number, y: number } {
let x = p2.x - p1.x;
let y = p2.y - p1.y;
var d = Math.sqrt(x * x + y * y);
if (d > 0) {
var id = 1.0 / d;
x *= id;
y *= id;
}
return { x: x, y: y }
}
/**
* 二维平面上 两点之间的距离
* @param p1 点1
* @param p2 点2
*/
public static distanceV2(p1: { x: number, y: number } | any, p2: { x: number, y: number } | any): number {
return Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2));
}
/**
* 二维矩阵中上 两点之间的距离,默认两个点之间的距离为1
* @param p1 点1
* @param p2 点2
*/
public static distanceM2(p1: {r:number, c:number}, p2: {r:number, c:number}): number {
return Math.sqrt(Math.pow(p1.r - p2.r, 2) + Math.pow(p1.c - p2.c, 2));
}
/**
* 根据开始位置和结束位置返回从开始位置到结束位置的朝向角度
* @param startPoint 开始位置
* @param endPoint 结束位置
* @returns 从开始位置朝向结束位置的角度0 - 360
*/
public static angle(startPoint: Point | { x, y }, endPoint: Point | { x, y }): number {
if (startPoint.x == endPoint.x && startPoint.y == endPoint.y) return 0;
let r = 0;
let xOffset = (endPoint.x - startPoint.x);
let yOffset = -(endPoint.y - startPoint.y);
if (xOffset > 0) {
if (yOffset > 0) { // 第一象限
r = Math.atan(xOffset / yOffset) * 180 / Math.PI;
} else { // 第四象限
r = Math.atan(-yOffset / xOffset) * 180 / Math.PI + 90;
}
} else {
if (yOffset > 0) { // 第二象限
r = 360 - Math.atan(-xOffset / yOffset) * 180 / Math.PI;
} else { // 第三象限
r = Math.atan(-xOffset / -yOffset) * 180 / Math.PI + 180;
}
}
return r;
}
/**
* 将角度转换为 0 - 360 之间
* @param rot
*/
public static formatRot(rot:number): number {
return ((rot % 360) + 360) % 360;
}
/**
* 获取一个接近的2D旋转角度
* @param currRot
* @param deltaRot 要旋转的角度
* @param tarRot
*/
public static getNearerRot(currRot:number, deltaRot:number, tarRot:number): number {
currRot = this.formatRot(currRot);
deltaRot = this.formatRot(deltaRot);
// tarRot = this.formatRot(tarRot);
let tarTempRot = this.formatRot(tarRot);
if(deltaRot >= 180) return tarRot;
let interval = Math.abs(tarTempRot - currRot); // 两个
if(interval < 180) {
if(interval <= deltaRot) return tarRot;
if(tarTempRot > currRot) {
return currRot + deltaRot;
} else {
return currRot - deltaRot;
}
} else {
if(interval - 180 <= deltaRot) return tarRot;
if(tarTempRot > currRot) {
return this.formatRot(currRot - deltaRot);
} else {
return this.formatRot(currRot + deltaRot);
}
}
}
/**
* 两个数中的最小数
* @param a
* @param b
*/
public static min(a: number, b: number): number {
return a < b ? a : b;
}
/**
* 两个数中的最大数
* @param a
* @param b
*/
public static max(a: number, b: number): number {
return a > b ? a : b;
}
/**
* 打印二维向量的字符串
* @param output 二维向量
*/
public static logV2(output: Laya.Point): void {
if (!output) {
MathE.error();
}
console.log(`(${output.x.toFixed(2)},${output.y.toFixed(2)})`);
}
/**
* 打印三维向量的字符串
* @param output 三维向量
*/
public static logV3(output: Laya.Vector3): void {
if (!output) {
MathE.error();
}
console.log(`(${output.x.toFixed(2)},${output.y.toFixed(2)},${output.z.toFixed(2)})`);
}
/**
* 输入警告
*/
public static error(): void {
console.error(`[MathE].*(): 错误的输入! `);
}
/**
* 求两个直线的方程的交点 ax + bx + c = 0, 下面两个三维向量分别存放参数a,b,c
* @param line0 直线方程参数
* @param line1 直线方程参数
*/
public static pointOfIntersection(line0: Laya.Vector3, line1: Laya.Vector3): Laya.Point {
let a0: number = line0.x; let b0: number = line0.y; let c0: number = line0.z;
let a1: number = line1.x; let b1: number = line1.y; let c1: number = line1.z;
let x: number = (c1 * b0 - c0 * b1) / (a0 * b1 - a1 * b0);
let y: number = - a0 / b0 * x - c0 / b0;
return new Laya.Point(x, y);
}
/**
* 随机一个正负1,用来做随机正反方向,位置或者数字等
*/
public static symbol(): number {
return Math.random() > 0.5 ? 1 : -1;
}
/**
* 正方形的对角线长度
* @param side 边长
*/
public static diagonalSquare(side: number): number {
return Math.sqrt(2 * side * side);
}
/**
* 3D坐标对应的2D坐标
* @param camera 摄像机
* @param position 3D位置
* @returns 2D屏幕上的位置
*/
public static v3PosTo2DPos(camera: Camera, position: Vector3): Vector2 {
let outPos: Vector4 = new Vector4();
camera.viewport.project(position, camera.projectionViewMatrix, outPos);
return new Vector2(outPos.x, outPos.y);
}
/**
* 根据一个2D物体的角度, 返回该角度对应的单位向量
* @param angle 2D物体的角度
* @returns
*/
public static angleToV2(angle: number): Point {
angle = angle < 0 ? (angle - (360 * Math.floor(angle / 360))) : angle % 360;
if (angle == 0) return new Point(0, -1);
if (angle == 90) return new Point(1, 0);
if (angle == 180) return new Point(0, 1);
if (angle == 270) return new Point(-1, 0);
let a = angle / 180 * Math.PI;
if (angle <= 90) {
return new Point(Math.sin(a), -Math.cos(a));
} else if (angle <= 180) {
a -= Math.PI / 2;
return new Point(Math.cos(a), Math.sin(a));
} else if (angle <= 270) {
a -= Math.PI;
return new Point(-Math.sin(a), Math.cos(a));
} else if (angle <= 360) {
a -= Math.PI * (3 / 2);
return new Point(-Math.cos(a), -Math.sin(a));
}
}
/**
* 反转
* @param x
*/
static reverse(x: number): number {
let MAX: number = 2147483647;
let MIN: number = -2147483648;
let sign: number = 1; // 记录当前整数的符号
if (x < 0) { // 将x变为正整数处理
sign = -1;
x = -x;
}
let result: number = 0;
while (x) {
result = (x % 10) + result * 10;
x = Math.floor(x / 10);
}
result *= sign;
return result > MAX || result < MIN ? 0 : result;
}
/**
* 字符串转数组,返回一个数组
* @param strToArrBool 字符串转数组 true 数组转字符串 false
* @param str 传入字符串
* @param splitStr 需要切割的特殊字符 例如: , . | 。等
*/
public static StrToArr(strToArrBool, str: string, splitStr, arr): any {
if (strToArrBool) {
//字符串转数组
if (str != null) {
return str.split(splitStr);
} else {
return [];
}
} else {
//数组转字符串
let str = "";
for (let index = 0; index < arr.length; index++) {
if (index == arr.length - 1) {
str += arr[index];
} else {
str += arr[index] + splitStr;
}
}
return str;
}
}
public static readonly AllStr: string = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
/**
* 获取一个随机字符串
* @param len 长度
*/
static getRandomStr(len: number): string {
let str: string = "";
let l: number = MathE.AllStr.length;
for (let i: number = 0; i < len; i++) {
str += MathE.AllStr.charAt(MathE.range(0, l, true));
}
return str;
}
/**
* 二分查找
* @param nums
* @param target
*/
static binarySearch(nums: Array<number>, target: number): number {
if (target < nums[0] || target > nums[nums.length - 1]) return -1;
let left: number = 0;
let right: number = nums.length - 1;
let middle: number = 0;
while (left <= right) {
middle = Math.floor((left + right) / 2);
if (nums[middle] == target) {
return middle;
} else {
if (nums[middle] > target) {
right = middle - 1;
} else {
left = middle + 1;
}
}
}
return -1;
}
/**
*
* @param str
* @param size
* @returns
*/
static hashFunc(str, size) {
//1.定义hashCode变量
var hashCode = 0
//2.霍纳算法,来计算 hashCode的值
for (var i = 0; i < str.length; i++) {
hashCode = 37 * hashCode + str.charCodeAt(i) //获取编码
}
//3.取余状态
var index = hashCode % size
return index
}
/**
* 2阶贝塞尔曲线函数
* @param p0 初始点
* @param p1 初始点与目标点之间找寻的一个控制点
* @param p2 目标点
* @param obj 做运动的对象
* @param time 时间变化 0-1
*/
public static TwoBsier(p0, p1, p2, obj, time) {
let x1 = p0.x + (p1.x - p0.x) * time;
let y1 = p0.y + (p1.y - p0.y) * time;
let x2 = p1.x + (p2.x - p1.x) * time;
let y2 = p1.y + (p2.y - p1.y) * time;
obj.x = x1 + (x2 - x1) * time;
obj.y = y1 + (y2 - y1) * time;
if (time < 1) {
return true
} else {
return false;
}
}
/**
* 返回两点之间的中心点
* @param p1 值1
* @param p2 值2
* @returns 返回值。number类型
*/
public static TwoPointMidPos(p1, p2): number {
if (p1 > 0 && p2 > 0) {
return Math.min(p1, p2) + ((Math.max(p1, p2) - Math.min(p1, p2)) * 0.5);
} else {
if (p1 <= 0 && p2 <= 0) {
return Math.max(p1, p2) + ((Math.min(p1, p2) - Math.max(p1, p2)) * 0.5);
} else {
if (p1 > 0) {
//p2 < 0
return (p1 - (p2 * -1)) * 0.5;
}
if (p2 > 0) {
//p1 < 0
return (p2 - (p1 * -1)) * 0.5;
}
}
}
}
/** 获取0-1的概率里的一个数 */
public static getRandomNum(rateType) {
let randomNumber = Math.random();
let startRate = 0;
for (let num in rateType) {
let rateTmp = rateType[num];
if (randomNumber > startRate && randomNumber <= startRate + rateTmp) {
return parseInt(num);
}
startRate += rateTmp;
}
return 10;
}
/** 判断该数字是否在某个范围内, 如果在直接返回该值, 否则返回边界值*/
public static inRange(num: number, min: number, max: number): number {
if (num < min) {
return min;
} else if (num > max) {
return max;
} else {
return num;
}
}
/**
* 获取贝塞尔曲线的点的集合
* @param points 点的集合, 至少包含起点和终点
* @param num 想要生成多少点
* @returns
*/
public static getCurvePointsInNum(points: Array<any>, num: number): Array<any> {
let result: Array<any> = new Array<any>();
for (let i: number = 0; i < num; i++) {
let t: number = i / (num - 1);
let point = this.getKeyPoint(points, t);
result.push(point);
}
return result;
}
public static getKeyPoint(points: Array<any>, t: number): any {
if (points.length > 1) {
let dirs: Array<any> = new Array<any>();
for (let i: number = 0; i < points.length - 1; i++) {
dirs.push({
x: points[i + 1].x - points[i].x,
y: points[i + 1].y - points[i].y
});
}
let points2: Array<any> = new Array<any>();
for (let j: number = 0; j < dirs.length; j++) {
points2.push({
x: points[j].x + dirs[j].x * t,
y: points[j].y + dirs[j].y * t
});
}
return this.getKeyPoint(points2, t);
} else {
return { x: points[0].x, y: points[0].y };
}
}
}
Laya 扩展Math类(待补充)
于 2020-07-01 17:22:44 首次发布
本文介绍了一套专为游戏开发设计的数学工具箱,涵盖随机数生成、向量操作、角度转换、几何计算等功能。通过具体实例展示了如何在游戏场景中应用这些数学函数,如角色定位、路径寻找、物体旋转等。

1866

被折叠的 条评论
为什么被折叠?



