角度转弧度
cc.misc.degreesToRadians(degree)
弧度转角度
cc.misc.radiansToDegrees(radian)
限定浮点数的最大最小值
cc.misc.clampf(x, y, z);
返回指定向量的弧度
Math.atan2(v.y, v.x)
将弧度转换为一个标准化后的向量,返回坐标 x = cos(a) , y = sin(a)
cc.v2(Math.cos(a), Math.sin(a))
返回指定 2 个向量之间的距离
p1.sub(p2).mag()
返回两个点之间距离的平方
p1.sub(p2).magSqr()
返回指定向量的长度
p.mag()
返回指定向量长度的平方
p.magSqr()
返回一个长度为 1 的标准化过后的向量
p.normalize()
//已知圆点,半径,角度,求圆周上的点
static getCirclePoint(origin: cc.Vec2, radius: number, degree: number)
{
//角度转弧度
let radian = cc.misc.degreesToRadians(degree);
let x = origin.x + radius * Math.cos(radian);
let y = origin.y + radius * Math.sin(radian);
return cc.v2(x, y);
}
//抛物线
static getParabola(duration: number, ptStart: cc.Vec2, ptEnd: cc.Vec2, height: number = 0, degree:number = 60)
{
//角度转弧度
let radian = cc.misc.degreesToRadians(degree);
//第一个控制点为抛物线左半弧的中点
let q1x = ptStart.x + (ptEnd.x - ptStart.x) / 4.0;
let q1 = cc.v2(q1x, height + ptStart.y + Math.cos(radian) * q1x);
// 第二个控制点为整个抛物线的中点
let q2x = ptStart.x + (ptEnd.x - ptStart.x) / 2.0;
let q2 = cc.v2(q2x, height + ptStart.y + Math.cos(radian) * q2x);
//贝塞尔曲线配置
let bezier = [q1, q2, ptEnd];
//使用easeInOut让曲线运动有一个由慢到快的变化,显得更自然
return cc.bezierTo(duration, bezier).easing(cc.easeInOut(0.8));
}
//求直线AB延长线上D的坐标,BD距离已知
/*
* 1. (yb-ya)/(xb-xa)= (yd - yb)/(xd-xb)
* 2. (yd-yb)^2 + (xd-xb)^2 = d^2
*
* 假设
* yab = yb-ya, xab = xb-xa
* ybd = yd-yb, xbd = xd-xb
* =>
* 3. yab/xab = ybd/xbd
* 4. ybd^2 + xbd^2 = d^2
*
* 由3得到
* 5 ybd = (yab/xab)*xbd
* 5 带入 4 得到
*
* 6. ((yab/xab)*xbd)^2 + xbd^2 = d^2
* =>
* 7. (xbd^2) * ((yab/xab)^2 + 1) = d^2
* =>
* 8. xbd^2 = (d^2)/((yab/xab)^2 + 1)
*
* 需要注意的是
* 1. yb-ya 和 yd-yb 的符号必须保持一致(因为在延长线上)
* 2. 暂时没有考虑 xb - xa == 0的情况
*/
static getLinePoint(ptA: cc.Vec2, ptB: cc.Vec2, distance: number)
{
let xab, yab;
let xbd, ybd;
let xd, yd;
xab = ptB.x - ptA.x;
yab = ptB.y - ptA.y;
xbd = Math.sqrt((distance * distance)/((yab/xab) * (yab/xab) + 1));
if (xab > 0) {
xbd = Math.sqrt((distance * distance)/((yab/xab) * (yab/xab) + 1));
} else {
xbd = -Math.sqrt((distance * distance)/((yab/xab) * (yab/xab) + 1));
}
if (distance < - EPSINON)
{
xd = ptB.x - xbd;
yd = ptB.y - yab / xab * xbd;
}
else if (distance > EPSINON)
{
xd = ptB.x + xbd;
yd = ptB.y + yab / xab * xbd;
}
return cc.v2(xd, yd);
}
//计算点P(x,y)与X轴正方向的夹角,返回夹角弧度
static getRadian(x, y)
{
//P在(0,0)的情况
if (x == 0 && y == 0) return 0;
//P在四个坐标轴上的情况:x正、x负、y正、y负
if (y == 0 && x > 0) return 0;
if (y == 0 && x < 0) return Math.PI;
if (x == 0 && y > 0) return Math.PI / 2;
if (x == 0 && y < 0) return Math.PI / 2 * 3;
//点在第一、二、三、四象限时的情况
if (x > 0 && y > 0) return Math.atan(y / x);
if (x < 0 && y > 0) return Math.PI - Math.atan(y / -x);
if (x < 0 && y < 0) return Math.PI + Math.atan(-y / -x);
if (x > 0 && y < 0) return Math.PI * 2 - Math.atan(-y / x);
return 0;
}
//求点P围绕点A旋转弧度radian后的坐标
static getRotatePoint(P: cc.Vec2, A: cc.Vec2, radian: number, clockwise = true)
{
//点Temp1
let Temp1 = cc.v2(P.x - A.x, P.y - A.y);
//点Temp1到原点的长度
let lenO2Temp1 = Temp1.sub(cc.v2(0,0)).mag();
//∠T1OX弧度
let angT1OX = this.getRadian(Temp1.x, Temp1.y);
//∠T2OX弧度(T2为T1以O为圆心旋转弧度rad)
let angT2OX = angT1OX - (clockwise ? 1 : -1) * radian;
//点Temp2
let Temp2 = cc.v2(lenO2Temp1 * Math.cos(angT2OX), lenO2Temp1 * Math.sin(angT2OX));
//点Q
return cc.v2(Temp2.x + A.x, Temp2.y + A.y);
}
//转向目标坐标
static getRotationToPoint(origin: cc.Vec2, target: cc.Vec2)
{
//向量差计算,结束点-开始点,向量的指向是朝着结束点
let delta = target.sub(origin);
//向量的角度计算,Math.atan2是获得弧度值,角度 = 弧度/PI*180
//let degree = Math.atan2(delta.y, delta.x) / Math.PI *180;
let degree = cc.misc.radiansToDegrees(Math.atan2(delta.y, delta.x));
//rotation是逆时针旋转的,在角度添加负号才正确
return -degree;
}