常用的数学方法

角度转弧度

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;
    }

 

转载于:https://my.oschina.net/valiancer/blog/3023368

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值