mathHelper优化及注释。修复pointCircle错误实现

This commit is contained in:
yhh
2023-03-13 14:51:38 +08:00
parent 64bd6aa055
commit 72fdabd099
6 changed files with 1166 additions and 647 deletions

View File

@@ -6259,14 +6259,16 @@ var es;
return p0 * amountCubed + p1 * amountSquared + p2 * amount + p3;
};
/**
* 将值在leftMin-leftMax范围内映射到一个在rightMin-rightMax范围内的值
* @param value
* @param leftMin
* @param leftMax
* @param rightMin
* @param rightMax
* 对给定值进行范围映射。
* @param value 要映射的值。
* @param leftMin 输入范围的最小值。
* @param leftMax 输入范围的最大值。
* @param rightMin 输出范围的最小值。
* @param rightMax 输出范围的最大值。
* @returns 映射后的值。
*/
MathHelper.map = function (value, leftMin, leftMax, rightMin, rightMax) {
// 使用线性插值公式进行映射
return rightMin + (value - leftMin) * (rightMax - rightMin) / (leftMax - leftMin);
};
/**
@@ -6280,26 +6282,29 @@ var es;
return (value - min) * 1 / (max - min);
};
/**
* 将值从某个任意范围映射到1到0范围
* 这相当于map01的取反
* 接收一个值value和两个边界min和max作为参数。它将value映射到0到1的范围内然后返回1减去该结果的值因此该函数的结果将在1到0之间
* @param value
* @param min
* @param max
* @returns
*/
MathHelper.map10 = function (value, min, max) {
return 1 - this.map01(value, min, max);
// 将 value 映射到 0 到 1 的范围内
var mappedValue = this.map01(value, min, max);
// 返回 1 减去 mappedValue 的值,结果将在 1 到 0 之间
return 1 - mappedValue;
};
/**
* 使用三次方程在两个值之间进行插值
* @param value1
* @param value2
* @param amount
* 在两个值之间进行平滑的线性插值。与 lerp 相似,但具有平滑过渡的特点,当 t 在 0 和 1 之间时,返回 [value1, value2] 之间平滑插值后的结果。
* @param value1 起始值
* @param value2 结束值
* @param amount 插值的程度,范围在 0 到 1 之间。
* @returns 两个值之间进行平滑的线性插值后的结果。
*/
MathHelper.smoothStep = function (value1, value2, amount) {
var result = this.clamp(amount, 0, 1);
result = MathHelper.hermite(value1, 0, value2, 0, result);
return result;
amount = this.clamp01(amount); // 将 amount 的值限制在 0 到 1 之间
amount = this.hermite(value1, 0, value2, 0, amount); // 使用 hermite 函数进行平滑插值
return amount; // 返回插值后的结果
};
/**
* 将给定角度减小到π到-π之间的值
@@ -6318,67 +6323,98 @@ var es;
}
};
/**
* 确定值是否以2为底
* 判断给定的数值是否是2的幂
* @param value
* @returns
*/
MathHelper.isPowerOfTwo = function (value) {
return (value > 0) && ((value % (value - 1)) == 0);
// 确保值大于0
if (value <= 0) {
return false;
}
// 检查是否为2的幂
return (value & (value - 1)) == 0;
};
/**
* 线性插值
* @param from
* @param to
* @param t
* @returns
*/
MathHelper.lerp = function (from, to, t) {
return from + (to - from) * this.clamp01(t);
// 计算在 from 和 to 之间 t 所占的比例
var clampedT = MathHelper.clamp01(t);
// 计算 from 到 to 的差值,再乘以比例,得到从 from 到 to 之间 t 所在的位置
return from + (to - from) * clampedT;
};
/**
* 线性插值前检查两个数的差是否小于一个给定的epsilon值如果小于则直接返回结束值b否则执行线性插值并返回插值结果。
* @param a 起始值
* @param b 结束值
* @param t 插值因子
* @param epsilon 差值阈值当两个数的差小于epsilon时直接返回结束值b。
* @returns 如果a和b的差小于给定的epsilon值则返回b否则返回a到b的插值结果。
*/
MathHelper.betterLerp = function (a, b, t, epsilon) {
return Math.abs(a - b) < epsilon ? b : MathHelper.lerp(a, b, t);
};
/**
* 使度数的角度在a和b之间
* 用于处理360度环绕
* @param a
* @param b
* @param t
* @returns
* 在两个角度之间进行插值,使用角度值表示角度
* @param a 起始角度
* @param b 结束角度
* @param t 插值比例,范围[0, 1]
* @returns 两个角度之间插值后的角度,使用角度值表示
*/
MathHelper.lerpAngle = function (a, b, t) {
var num = this.repeat(b - a, 360);
if (num > 180)
num -= 360;
return a + num * this.clamp01(t);
// 计算从a到b的差值对于超过360的值需要进行修正
var deltaAngle = this.repeat(b - a, 360);
if (deltaAngle > 180) {
deltaAngle -= 360;
}
// 返回经过插值后的角度
return a + deltaAngle * this.clamp01(t);
};
/**
* 使弧度的角度在a和b之间
* @param a
* @param b
* @param t
* @returns
* 在两个角度之间进行插值,使用弧度值表示角度
* @param a 起始角度
* @param b 结束角度
* @param t 插值比例,范围[0, 1]
* @returns 两个角度之间插值后的角度,使用弧度值表示
*/
MathHelper.lerpAngleRadians = function (a, b, t) {
var num = this.repeat(b - a, Math.PI * 2);
if (num > Math.PI)
num -= Math.PI * 2;
return a + num * this.clamp01(t);
// 计算从a到b的差值对于超过2π的值需要进行修正
var deltaAngle = this.repeat(b - a, Math.PI * 2);
if (deltaAngle > Math.PI) {
deltaAngle -= Math.PI * 2;
}
// 返回经过插值后的角度
return a + deltaAngle * this.clamp01(t);
};
/**
* 循环t使其不大于长度且不小于0
* @param t
* @param length
* @returns
* 指定长度上来回“弹跳”ping-pong一个变量
* 因为弹跳的过程是来回循环的。最后根据t在弹跳过程中相对于length的位置
* @param t 变量的当前值
* @param length 指定的长度
* @returns 0到length之间变化的值
*/
MathHelper.pingPong = function (t, length) {
// 将t的值限制在0到length*2的范围内
t = this.repeat(t, length * 2);
// 返回length和t-length的差的绝对值
return length - Math.abs(t - length);
};
/**
* 如果value> = threshold返回符号否则返回0
* @param value
* @param threshold
* @returns
* value的绝对值大于等于threshold返回value的符号否则返回0
* @param value - 输入的值
* @param threshold - 阈值
* @returns value的符号或0
*/
MathHelper.signThreshold = function (value, threshold) {
if (Math.abs(value) >= threshold)
return Math.sign(value);
if (Math.abs(value) >= threshold) // 如果绝对值大于等于阈值
return Math.sign(value); // 返回value的符号
else
return 0;
return 0; // 否则返回0
};
/**
* 计算t值在[from, to]区间内的插值比例
@@ -6398,31 +6434,42 @@ var es;
return (t - from) / length;
};
/**
* 在两个值之间线性插值
* 此方法是MathHelper.Lerp的效率较低更精确的版本。
* 精确的线性插值,避免出现累积误差
* @param value1 起始值
* @param value2 结束值
* @param amount 插值比例
* @returns 两个值的线性插值结果
*/
MathHelper.lerpPrecise = function (value1, value2, amount) {
return ((1 - amount) * value1) + (value2 * amount);
};
/**
* 将给定值限制在指定范围内
* @param value 需要被限制的值
* @param min 最小值
* @param max 最大值
* @returns 限制后的值
*/
MathHelper.clamp = function (value, min, max) {
if (value < min)
if (value < min) { // 如果值小于最小值,则返回最小值
return min;
if (value > max)
}
else if (value > max) { // 如果值大于最大值,则返回最大值
return max;
return value;
};
MathHelper.snap = function (value, increment) {
return Math.round(value / increment) * increment;
}
else { // 否则返回原始值
return value;
}
};
/**
* 给定圆心、半径和角度得到圆周上的一个点。0度是3点钟。
* @param circleCenter
* @param radius
* @param angleInDegrees
* 按照指定增量取整到最接近的整数倍数
* @param value
* @param increment
* @returns
*/
MathHelper.pointOnCirlce = function (circleCenter, radius, angleInDegrees) {
var radians = MathHelper.toRadians(angleInDegrees);
return new es.Vector2(Math.cos(radians) * radians + circleCenter.x, Math.sin(radians) * radians + circleCenter.y);
MathHelper.snap = function (value, increment) {
// 将给定值除以增量取整后再乘以增量,得到最接近给定值的整数倍
return Math.round(value / increment) * increment;
};
/**
* 如果值为偶数返回true
@@ -6440,10 +6487,10 @@ var es;
return value % 2 != 0;
};
/**
* 将值四舍五入并返回它和四舍五入的数
* @param value
* @param roundedAmount
* @returns
* 将值四舍五入到最接近的整数,并计算四舍五入的数
* @param value 要四舍五入的数值
* @param roundedAmount 用于存储四舍五入的数量的参数
* @returns 四舍五入后的整数
*/
MathHelper.roundWithRoundedAmount = function (value, roundedAmount) {
var rounded = Math.round(value);
@@ -6451,8 +6498,9 @@ var es;
return rounded;
};
/**
* 数值限定在0-1之间
* @param value
* 将一个数值限制在 [0,1] 范围内
* @param value 要限制的数值
* @returns 限制后的数值
*/
MathHelper.clamp01 = function (value) {
if (value < 0)
@@ -6461,230 +6509,345 @@ var es;
return 1;
return value;
};
/**
* 计算从一个向量到另一个向量之间的角度
* @param from 起始向量
* @param to 目标向量
* @returns 两个向量之间的角度(弧度制)
*/
MathHelper.angleBetweenVectors = function (from, to) {
// 使用 Math.atan2() 方法计算出两个向量之间的夹角,返回的是弧度制角度
return Math.atan2(to.y - from.y, to.x - from.x);
};
/**
* 将极角和极径转换为向量坐标
* @param angleRadians 极角弧度值
* @param length 极径长度
* @returns 对应向量坐标
*/
MathHelper.angleToVector = function (angleRadians, length) {
return new es.Vector2(Math.cos(angleRadians) * length, Math.sin(angleRadians) * length);
// 根据给定的极角弧度值使用三角函数计算出向量的x坐标和y坐标
var x = Math.cos(angleRadians) * length;
var y = Math.sin(angleRadians) * length;
// 使用上一步得到的坐标值创建一个新的Vector2对象并返回
return new es.Vector2(x, y);
};
/**
* 增加t并确保它总是大于或等于0并且小于长度
* @param t
* @param length
* 将一个数加上1并在结果等于指定长度时将其设置为0
* @param t 要加上1的数
* @param length 指定长度
* @returns 加上1后的结果如果等于指定长度则为0
*/
MathHelper.incrementWithWrap = function (t, length) {
// 将给定数t加上1。
t++;
if (t == length)
// 如果结果等于指定长度则返回0。
if (t == length) {
return 0;
}
// 否则,返回结果。
return t;
};
/**
* 递减t并确保其始终大于或等于0且小于长度
* @param t
* @param length
* @returns
* 将一个数减去1并在结果小于0时将其设置为指定长度减去1
* @param t 要减去1的数
* @param length 指定长度
* @returns 减去1后的结果如果小于0则为指定长度减去1
*/
MathHelper.decrementWithWrap = function (t, length) {
// 将给定数t减去1。
t--;
if (t < 0)
// 如果结果小于0则返回指定长度减去1。
if (t < 0) {
return length - 1;
}
// 否则,返回结果。
return t;
};
/**
* 返回sqrtx * x + y * y
* @param x
* @param y
* @returns
* 计算直角三角形斜边长度,即求两个数的欧几里得距离
* @param x 直角三角形的一条直角边
* @param y 直角三角形的另一条直角边
* @returns 三角形斜边长度
*/
MathHelper.hypotenuse = function (x, y) {
return Math.sqrt(x * x + y * y);
// 将x的平方与y的平方相加。
var sumOfSquares = x * x + y * y;
// 对和进行平方根运算。
var result = Math.sqrt(sumOfSquares);
// 返回结果。
return result;
};
/**
* 计算大于给定数字的最小二次幂
* @param x 给定数字
* @returns 大于给定数字的最小二次幂
*/
MathHelper.closestPowerOfTwoGreaterThan = function (x) {
x--;
x |= (x >> 1);
x--; // 将给定数字减1得到一个二进制数的掩码。
x |= (x >> 1); // 将掩码的右侧一半全部设置为1。
x |= (x >> 2);
x |= (x >> 4);
x |= (x >> 8);
x |= (x >> 16);
return (x + 1);
x |= (x >> 16); // 连续将掩码右移并将右侧一半全部设置为1直到得到一个全为1的掩码。
return (x + 1); // 将全为1的掩码加1得到的结果就是大于给定数字的最小二次幂。
};
/**
* 以roundToNearest为步长将值舍入到最接近的数字。例如在125中找到127到最近的5个结果
* @param value
* @param roundToNearest
* 将数字舍入到最接近的指定值
* @param value 需要被舍入的数字
* @param roundToNearest 指定的舍入值
* @returns 舍入后的结果
*/
MathHelper.roundToNearest = function (value, roundToNearest) {
return Math.round(value / roundToNearest) * roundToNearest;
var quotient = value / roundToNearest; // 将数字除以指定值,得到商。
var roundedQuotient = Math.round(quotient); // 将商四舍五入到最接近的整数。
var result = roundedQuotient * roundToNearest; // 将舍入后的整数乘以指定值,得到最终结果。
return result;
};
/**
* 检查传递的值是否在某个阈值之下。对于小规模、精确的比较很有用
* @param value
* @param ep
* 判断给定值是否接近于零
* @param value 给定值
* @param ep 阈值可选默认为Epsilon
* @returns 如果接近于零返回true否则返回false
*/
MathHelper.withinEpsilon = function (value, ep) {
if (ep === void 0) { ep = this.Epsilon; }
// 判断给定值的绝对值是否小于给定的阈值ep。
return Math.abs(value) < ep;
};
/**
* 由上移量向上移。start可以小于或大于end。例如:开始是2结束是10移位是4结果是6
* @param start
* @param end
* @param shift
* 逐渐逼近目标值
* @param start 起始值
* @param end 目标值
* @param shift 逼近步长
* @returns 逼近后的值
*/
MathHelper.approach = function (start, end, shift) {
if (start < end)
// 判断起始值是否小于目标值。
if (start < end) {
// 如果是返回起始值加上shift和目标值中的较小值。
return Math.min(start + shift, end);
}
// 如果不是返回起始值减去shift和目标值中的较大值。
return Math.max(start - shift, end);
};
/**
* 通过偏移量钳位结果并选择最短路径,将起始角度向终止角度移动,起始值可以小于或大于终止值。
* 示例1开始是30结束是100移位是25结果为55
* 示例2开始是340结束是30移位是25结果是5365换为5
* @param start
* @param end
* @param shift
* @returns
* 逐渐逼近目标角度
* @param start 起始角度
* @param end 目标角度
* @param shift 逼近步长
* @returns 最终角度
*/
MathHelper.approachAngle = function (start, end, shift) {
// 调用this.deltaAngle()方法,获取起始角度和目标角度之间的夹角。
var deltaAngle = this.deltaAngle(start, end);
if (-shift < deltaAngle && deltaAngle < shift)
// 判断夹角是否小于等于shift如果是直接返回目标角度。
if (-shift < deltaAngle && deltaAngle < shift) {
return end;
return this.repeat(this.approach(start, start + deltaAngle, shift), 360);
}
// 如果夹角大于shift则调用this.approach()方法,逐渐逼近目标角度。
var newAngle = this.approach(start, start + deltaAngle, shift);
// 通过调用this.repeat()方法将最终的角度限制在0到360度之间。
newAngle = this.repeat(newAngle, 360);
// 返回最终的角度。
return newAngle;
};
/**
* 将 Vector 投影到另一个 Vector 上
* @param other
* 计算向量在另一个向量上的投影向量
* @param self 要投影的向量
* @param other 目标向量
* @returns 投影向量
*/
MathHelper.project = function (self, other) {
// 通过调用Vector2.dot()方法计算出self向量和other向量的点积。
var amt = self.dot(other) / other.lengthSquared();
// 通过调用Vector2.lengthSquared()方法计算出other向量的长度的平方。
// 将点积除以长度的平方得到self向量在other向量上的投影长度。
// 通过调用Vector2.scale()方法将投影长度与other向量的方向向量相乘得到投影向量。
var vec = other.scale(amt);
// 返回投影向量。
return vec;
};
/**
* 通过将偏移量(全部以弧度为单位)夹住结果并选择最短路径,起始角度朝向终止角度。
* 起始值可以小于或大于终止值。
* 此方法的工作方式与“角度”方法非常相似唯一的区别是使用弧度代替度并以2 * Pi代替360。
* @param start
* @param end
* @param shift
* @returns
* 逐渐接近目标角度
* @param start 当前角度值(弧度制)
* @param end 目标角度值(弧度制)
* @param shift 每次逐渐接近目标角度的增量(弧度制)
* @returns 逐渐接近目标角度后的角度值(弧度制)
*/
MathHelper.approachAngleRadians = function (start, end, shift) {
// 通过调用deltaAngleRadians()方法,计算出当前角度值和目标角度值之间的弧度差值。
var deltaAngleRadians = this.deltaAngleRadians(start, end);
if (-shift < deltaAngleRadians && deltaAngleRadians < shift)
// 如果弧度差值的绝对值小于shift则返回目标角度值。
if (-shift < deltaAngleRadians && deltaAngleRadians < shift) {
return end;
return this.repeat(this.approach(start, start + deltaAngleRadians, shift), Math.PI * 2);
}
// 否则通过调用approach()方法,逐渐将当前角度值接近目标角度值。
var result = this.approach(start, start + deltaAngleRadians, shift);
// 将计算结果使用repeat()方法转换成[0, 2π)之间的角度值,并返回。
return this.repeat(result, Math.PI * 2);
};
/**
* 使用可接受的检查公差检查两个值是否大致相同
* @param value1
* @param value2
* @param tolerance
* @returns
* 判断两个值是否在指定公差内近似相等
* @param value1 第一个数值
* @param value2 第二个数值
* @param tolerance 指定公差,默认为 Epsilon 常量
* @returns 是否在指定公差内近似相等
*/
MathHelper.approximately = function (value1, value2, tolerance) {
if (tolerance === void 0) { tolerance = this.Epsilon; }
// 计算两个数值之差的绝对值是否小于等于指定公差。
return Math.abs(value1 - value2) <= tolerance;
};
/**
* 计算两个给定角之间的最短差值(度数)
* @param current
* @param target
* 计算两个角度值之间的角度差值
* @param current 当前角度值
* @param target 目标角度值
* @returns 角度差值
*/
MathHelper.deltaAngle = function (current, target) {
// 通过调用repeat()方法,计算出当前角度值和目标角度值之间的差值。
var num = this.repeat(target - current, 360);
if (num > 180)
// 如果差值大于180度则将差值减去360度得到[-180度, 180度]之间的差值。
if (num > 180) {
num -= 360;
}
// 返回差值。
return num;
};
/**
* 检查值是否介于最小值/最大值(包括最小值/最大值)之间
* @param value
* @param min
* @param max
* @returns
* 判断给定数值是否在指定区间内
* @param value 给定数值
* @param min 区间最小值
* @param max 区间最大值
* @returns 是否在指定区间内
*/
MathHelper.between = function (value, min, max) {
// 比较给定数值是否大于等于最小值并且小于等于最大值。
return value >= min && value <= max;
};
/**
* 计算以弧度为单位的两个给定角度之间的最短差
* @param current
* @param target
* @returns
* 计算两个弧度值之间的角度差值
* @param current 当前弧度值
* @param target 目标弧度值
* @returns 角度差值
*/
MathHelper.deltaAngleRadians = function (current, target) {
// 通过调用repeat()方法,计算出当前弧度值和目标弧度值之间的差值。
var num = this.repeat(target - current, 2 * Math.PI);
if (num > Math.PI)
// 如果差值大于π则将差值减去2π得到[-π, π]之间的差值。
if (num > Math.PI) {
num -= 2 * Math.PI;
}
// 返回差值。
return num;
};
/**
* 循环t使其永远不大于长度永远不小于0
* @param t
* @param length
* 将给定的数值限定在一个循环范围内
* @param t 给定的数值
* @param length 循环范围长度
* @returns 限定在循环范围内的数值
*/
MathHelper.repeat = function (t, length) {
return t - Math.floor(t / length) * length;
};
MathHelper.floorToInt = function (f) {
return this.toInt(Math.floor(f));
// 计算给定数值除以循环范围长度的整数部分,即循环次数。
var num = Math.floor(t / length);
// 用给定数值减去循环次数乘以循环范围长度,得到限定在循环范围内的数值。
var result = t - num * length;
// 返回限定后的数值。
return result;
};
/**
* 将值绕一圈移动的助手
* @param position
* @param speed
* @returns
* 将给定的浮点数向下取整为整数
* @param f 给定的浮点数
* @returns 向下取整后的整数
*/
MathHelper.floorToInt = function (f) {
// 使用Math.floor()方法,将给定的浮点数向下取整为最接近它的小于等于它的整数。
var flooredValue = Math.floor(f);
// 调用toInt()方法,将结果转换为整数类型。
return this.toInt(flooredValue);
};
/**
* 绕着一个点旋转
* @param position 原点坐标
* @param speed 旋转速度
* @returns 经过旋转后的点坐标
*/
MathHelper.rotateAround = function (position, speed) {
var time = es.Time.totalTime * speed;
var x = Math.cos(time);
var y = Math.sin(time);
return new es.Vector2(position.x + x, position.y + y);
};
/**
* 旋转是相对于当前位置而不是总旋转。
* 例如如果您当前处于90度并且想要旋转到135度则可以使用45度而不是135度的角度
* @param point
* @param center
* @param angleIndegrees
*/
MathHelper.rotateAround2 = function (point, center, angleIndegrees) {
angleIndegrees = this.toRadians(angleIndegrees);
var cos = Math.cos(angleIndegrees);
var sin = Math.sin(angleIndegrees);
var rotatedX = cos * (point.x - center.x) - sin * (point.y - center.y) + center.x;
var rotatedY = sin * (point.x - center.x) + cos * (point.y - center.y) + center.y;
// 计算旋转角度,使用当前时间与旋转速度的乘积作为参数进行计算。
var angleInRadians = es.Time.totalTime * speed;
// 通过三角函数计算出在当前时间下距离原点为1的点在x轴和y轴上的坐标值。
var cosValue = Math.cos(angleInRadians);
var sinValue = Math.sin(angleInRadians);
// 将计算出的x轴和y轴的坐标值加上原点的坐标值得到旋转后的点的坐标值。
var rotatedX = position.x + cosValue;
var rotatedY = position.y + sinValue;
// 创建一个新的Vector2对象将上面得到的旋转后的点的坐标值作为参数返回该对象。
return new es.Vector2(rotatedX, rotatedY);
};
/**
* 根据圆的中心,半径和角度在圆的圆周上得到一个点。 0度是3点钟方向
* @param circleCenter
* @param radius
* @param angleInDegrees
* 绕给定中心点旋转指定角度后得到的新点坐标
* @param point 要旋转的点的坐标
* @param center 旋转中心点的坐标
* @param angleIndegrees 旋转的角度,单位为度
* @returns 旋转后的新点的坐标返回值类型为Vector2
*/
MathHelper.rotateAround2 = function (point, center, angleIndegrees) {
var cx = center.x, cy = center.y;
var px = point.x, py = point.y;
var angleInRadians = this.toRadians(angleIndegrees); // 将角度值转换为弧度值
var cos = Math.cos(angleInRadians); // 计算cos值
var sin = Math.sin(angleInRadians); // 计算sin值
var rotatedX = cos * (px - cx) - sin * (py - cy) + cx; // 计算旋转后的新点的x坐标
var rotatedY = sin * (px - cx) + cos * (py - cy) + cy; // 计算旋转后的新点的y坐标
return new es.Vector2(rotatedX, rotatedY); // 返回旋转后的新点的坐标
};
/**
* 计算以给定点为圆心、给定半径的圆上某一点的坐标
* @param circleCenter 圆心坐标
* @param radius 圆半径
* @param angleInDegrees 角度值(度数制)
* @returns 计算出的圆上某一点的坐标
*/
MathHelper.pointOnCircle = function (circleCenter, radius, angleInDegrees) {
// 将给定角度值转换为弧度值,以便使用三角函数计算坐标值。
var radians = this.toRadians(angleInDegrees);
return new es.Vector2(Math.cos(radians) * radius + circleCenter.x, Math.sin(radians) * radius + circleCenter.y);
// 根据弧度值通过三角函数cos和sin计算出该角度对应的x和y坐标的值其中x坐标对应cos值y坐标对应sin值
var x = Math.cos(radians) * radius;
var y = Math.sin(radians) * radius;
// 将x坐标值乘以半径再加上圆心的x坐标得到该点在x轴上的绝对坐标。
var absoluteX = x + circleCenter.x;
// 将y坐标值乘以半径再加上圆心的y坐标得到该点在y轴上的绝对坐标。
var absoluteY = y + circleCenter.y;
// 创建一个新的Vector2对象将上面得到的x和y坐标作为参数返回该对象。
return new es.Vector2(absoluteX, absoluteY);
};
/**
* 根据圆的中心,半径和角度在圆的圆周上得到一个点。 0弧度是3点钟方向
* @param circleCenter
* @param radius
* @param angleInRadians
* @returns
* 计算以给定点为圆心、给定半径的圆上某一点的坐标
* @param circleCenter 圆心坐标
* @param radius 圆半径
* @param angleInRadians 角度值(弧度制)
* @returns 计算出的圆上某一点的坐标
*/
MathHelper.pointOnCircleRadians = function (circleCenter, radius, angleInRadians) {
return new es.Vector2(Math.cos(angleInRadians) * radius + circleCenter.x, Math.sin(angleInRadians) * radius + circleCenter.y);
// 根据给定角度值通过三角函数cos和sin计算出该角度对应的x和y坐标的值其中x坐标对应cos值y坐标对应sin值
var x = Math.cos(angleInRadians) * radius;
var y = Math.sin(angleInRadians) * radius;
// 将x坐标值乘以半径再加上圆心的x坐标得到该点在x轴上的绝对坐标。
var absoluteX = x + circleCenter.x;
// 将y坐标值乘以半径再加上圆心的y坐标得到该点在y轴上的绝对坐标。
var absoluteY = y + circleCenter.y;
// 创建一个新的Vector2对象将上面得到的x和y坐标作为参数返回该对象。
return new es.Vector2(absoluteX, absoluteY);
};
/**
* lissajou曲线
* @param xFrequency
* @param yFrequency
* @param xMagnitude
* @param yMagnitude
* @param phase
* @returns
* 生成一个Lissajous曲线上的点的坐标
* @param xFrequency x方向上的频率默认值为2
* @param yFrequency y方向上的频率默认值为3
* @param xMagnitude x方向上的振幅默认值为1
* @param yMagnitude y方向上的振幅默认值为1
* @param phase 相位默认值为0
* @returns 在Lissajous曲线上的点的坐标返回值类型为Vector2
*/
MathHelper.lissajou = function (xFrequency, yFrequency, xMagnitude, yMagnitude, phase) {
if (xFrequency === void 0) { xFrequency = 2; }
@@ -6692,9 +6855,9 @@ var es;
if (xMagnitude === void 0) { xMagnitude = 1; }
if (yMagnitude === void 0) { yMagnitude = 1; }
if (phase === void 0) { phase = 0; }
var x = Math.sin(es.Time.totalTime * xFrequency + phase) * xMagnitude;
var y = Math.cos(es.Time.totalTime * yFrequency) * yMagnitude;
return new es.Vector2(x, y);
var x = Math.sin(es.Time.totalTime * xFrequency + phase) * xMagnitude; // 计算x方向上的坐标
var y = Math.cos(es.Time.totalTime * yFrequency) * yMagnitude; // 计算y方向上的坐标
return new es.Vector2(x, y); // 返回在Lissajous曲线上的点的坐标
};
/**
* 生成阻尼的 Lissajous 曲线
@@ -6754,63 +6917,109 @@ var es;
return result;
};
/**
* 此函数用于确保数不是NaN或无穷大
* 判断给定的数字是否有效
* 如果输入的数字是 NaN 或正无穷大,该函数将返回 false否则返回 true
* @param x
* @returns
*/
MathHelper.isValid = function (x) {
// 如果输入的数字是 NaN返回 false
if (Number.isNaN(x)) {
return false;
}
return x !== Infinity;
};
MathHelper.smoothDamp = function (current, target, currentVelocity, smoothTime, maxSpeed, deltaTime) {
smoothTime = Math.max(0.0001, smoothTime);
var num = 2 / smoothTime;
var num2 = num * deltaTime;
var num3 = 1 /
(1 + (num2 + (0.48 * (num2 * num2) + 0.235 * (num2 * (num2 * num2)))));
var num4 = current - target;
var num5 = target;
var num6 = maxSpeed * smoothTime;
num4 = this.clamp(num4, num6 * -1, num6);
target = current - num4;
var num7 = (currentVelocity + num * num4) * deltaTime;
currentVelocity = (currentVelocity - num * num7) * num3;
var num8 = target + (num4 + num7) * num3;
if (num5 - current > 0 === num8 > num5) {
num8 = num5;
currentVelocity = (num8 - num5) / deltaTime;
// 如果输入的数字是正无穷大,返回 false
// 注意,负无穷大在这里被认为是有效的数字
if (x === Infinity) {
return false;
}
return { value: num8, currentVelocity: currentVelocity };
};
MathHelper.smoothDampVector = function (current, target, currentVelocity, smoothTime, maxSpeed, deltaTime) {
var v = es.Vector2.zero;
var resX = this.smoothDamp(current.x, target.x, currentVelocity.x, smoothTime, maxSpeed, deltaTime);
v.x = resX.value;
currentVelocity.x = resX.currentVelocity;
var resY = this.smoothDamp(current.y, target.y, currentVelocity.y, smoothTime, maxSpeed, deltaTime);
v.y = resY.value;
currentVelocity.y = resY.currentVelocity;
return v;
// 如果输入的数字既不是 NaN也不是正无穷大返回 true
return true;
};
/**
* 将值(在 leftMin - leftMax 范围内)映射到 rightMin - rightMax 范围内的值
* @param value
* @param leftMin
* @param leftMax
* @param rightMin
* @param rightMax
* 平滑阻尼运动,将当前位置平滑过渡到目标位置,返回一个包含当前位置和当前速度的对象
* @param current 当前位置
* @param target 目标位置
* @param currentVelocity 当前速度
* @param smoothTime 平滑时间
* @param maxSpeed 最大速度
* @param deltaTime 时间增量
* @returns 一个包含当前位置和当前速度的对象,类型为{ value: number; currentVelocity: number }
*/
MathHelper.smoothDamp = function (current, target, currentVelocity, smoothTime, maxSpeed, deltaTime) {
smoothTime = Math.max(0.0001, smoothTime); // 平滑时间至少为0.0001避免出现除以0的情况
var omega = 2 / smoothTime; // 根据平滑时间计算阻尼系数
var x = omega * deltaTime; // 计算阻尼系数与时间增量的乘积
var exp = 1 / (1 + 0.48 * x + 0.235 * x * x); // 计算阻尼比
var maxDelta = maxSpeed * smoothTime; // 计算最大速度与平滑时间的乘积
var delta = current - target; // 计算当前位置与目标位置之间的距离
delta = MathHelper.clamp(delta, -maxDelta, maxDelta); // 将距离限制在最大速度和最大速度的相反数之间
target = current - delta; // 计算新的目标位置
var temp = (currentVelocity + omega * delta) * deltaTime; // 计算当前速度和阻尼力的和乘以时间增量
currentVelocity = (currentVelocity - omega * temp) * exp; // 计算新的当前速度
var newValue = target + (delta + temp) * exp; // 计算新的当前位置
if (current > target === newValue > target) { // 如果新的当前位置超过了目标位置,则将当前位置设置为目标位置,并计算新的当前速度
newValue = target;
currentVelocity = (newValue - target) / deltaTime;
}
return { value: newValue, currentVelocity: currentVelocity }; // 返回包含当前位置和当前速度的对象
};
/**
* 平滑插值两个二维向量
* @param current 当前向量
* @param target 目标向量
* @param currentVelocity 当前速度向量
* @param smoothTime 平滑插值时间
* @param maxSpeed 最大速度
* @param deltaTime 帧间隔时间
* @returns 插值后的结果向量
*/
MathHelper.smoothDampVector = function (current, target, currentVelocity, smoothTime, maxSpeed, deltaTime) {
var v = es.Vector2.zero; // 创建一个初始向量v其x和y坐标都为0。
// 对当前向量的x和y坐标进行平滑插值得到插值结果和当前速度。
var resX = this.smoothDamp(current.x, target.x, currentVelocity.x, smoothTime, maxSpeed, deltaTime);
v.x = resX.value; // 将插值结果赋值给向量v的x坐标。
currentVelocity.x = resX.currentVelocity; // 将当前速度赋值给向量currentVelocity的x坐标。
var resY = this.smoothDamp(current.y, target.y, currentVelocity.y, smoothTime, maxSpeed, deltaTime);
v.y = resY.value; // 将插值结果赋值给向量v的y坐标。
currentVelocity.y = resY.currentVelocity; // 将当前速度赋值给向量currentVelocity的y坐标。
return v; // 返回向量v。
};
/**
* 将一个值从一个区间映射到另一个区间
* @param value 需要映射的值
* @param leftMin 所在区间的最小值
* @param leftMax 所在区间的最大值
* @param rightMin 需要映射到的目标区间的最小值
* @param rightMax 需要映射到的目标区间的最大值
* @returns
*/
MathHelper.mapMinMax = function (value, leftMin, leftMax, rightMin, rightMax) {
return rightMin + ((MathHelper.clamp(value, leftMin, leftMax) - leftMin) * (rightMax - rightMin)) / (leftMax - leftMin);
// 先将 value 限制在 [leftMin, leftMax] 区间内
var clampedValue = MathHelper.clamp(value, leftMin, leftMax);
// 计算映射到 [rightMin, rightMax] 区间内的值
return rightMin + (clampedValue - leftMin) * (rightMax - rightMin) / (leftMax - leftMin);
};
/**
* 返回一个给定角度的单位向量。角度被解释为弧度制。
* @param angle - 给定角度,以弧度制表示。
* @returns 一个新的已归一化的二维向量。
*/
MathHelper.fromAngle = function (angle) {
// 返回一个新的二维向量其中x和y分别设置为给定角度的余弦和正弦值然后进行归一化以产生单位向量。
return new es.Vector2(Math.cos(angle), Math.sin(angle)).normalizeEqual();
};
/**
* 将一个数字转换为最接近的整数
* @param val 需要被转换的数字
* @returns 最接近的整数
*/
MathHelper.toInt = function (val) {
return val > 0 ? Math.floor(val) : Math.ceil(val);
if (val > 0) { // 如果数字大于0则向下舍入为最接近的整数。
return Math.floor(val);
}
else { // 如果数字小于等于0则向上舍入为最接近的整数。
return Math.ceil(val);
}
};
MathHelper.Epsilon = 0.00001;
MathHelper.Rad2Deg = 57.29578;
@@ -9125,7 +9334,7 @@ var es;
var offsetAngle = Math.atan2(collider.localOffset.y * collider.entity.transform.scale.y, collider.localOffset.x * collider.entity.transform.scale.x) * es.MathHelper.Rad2Deg;
var offsetLength = hasUnitScale ? collider._localOffsetLength :
collider.localOffset.multiply(collider.entity.transform.scale).magnitude();
this.center = es.MathHelper.pointOnCirlce(es.Vector2.zero, offsetLength, collider.entity.transform.rotationDegrees + offsetAngle);
this.center = es.MathHelper.pointOnCircle(es.Vector2.zero, offsetLength, collider.entity.transform.rotationDegrees + offsetAngle);
}
es.Matrix2D.createTranslation(this._polygonCenter.x, this._polygonCenter.y, tempMat);
es.Matrix2D.multiply(combinedMatrix_1, tempMat, combinedMatrix_1);
@@ -9334,7 +9543,7 @@ var es;
// 为了处理偏移原点的旋转,我们只需要将圆心围绕(0,0)在一个圆上移动我们的偏移量就是0角
var offsetAngle = Math.atan2(collider.localOffset.y, collider.localOffset.x) * es.MathHelper.Rad2Deg;
var offsetLength = hasUnitScale ? collider._localOffsetLength : collider.localOffset.multiply(collider.entity.transform.scale).magnitude();
this.center = es.MathHelper.pointOnCirlce(es.Vector2.zero, offsetLength, collider.entity.transform.rotation + offsetAngle);
this.center = es.MathHelper.pointOnCircle(es.Vector2.zero, offsetLength, collider.entity.transform.rotation + offsetAngle);
}
}
this.position = collider.transform.position.add(this.center);