cocos2d-js 生成轴对称贝塞尔曲线并沿着曲线移动

首先要将startPoint和endPoint转化成一个y轴坐标,然后控制controlPoint_1和controlPoint_2来绘制一个轴对称的抛物线,用height来控制抛物线高度

/*创建一个抛物线动作
参数:
    time            时间
    startPoint      开始点
    endPoint        结束点
    height          高度(影响抛物线的高度)
    angle           角度(贝塞尔曲线两个控制点与y轴的夹角,直接影响精灵的抛出角度)
*/
createBezierLinsBetweenIslands: function(linePanel, startPoint, endPoint, islast) {
    var flipx = (endPoint.x < startPoint.x) ? true : false;
    linePanel.setAnchorPoint(cc.p(0, 0));
    linePanel.setPosition(startPoint);
    var radian = 0;
    if (endPoint.y != startPoint.y) {
        var dirCur = cc.p(endPoint.x - startPoint.x, endPoint.y - startPoint.y);
        var normal = cc.p(1, 0);
        radian = cc.pAngleSigned(dirCur, normal);
        var angle = radian / 3.1415926 * 180.0;
        linePanel.setRotation(angle);
        linePanel.lineRotation = angle;
        endPoint.x = startPoint.x + (endPoint.x - startPoint.x) / Math.cos(radian);
        endPoint.y = startPoint.y;
    }

    // 创建贝塞尔曲线
    var height = 150;
    // 第一个控制点为抛物线左半弧的中点  
    var q1x = startPoint.x + (endPoint.x - startPoint.x) * 0.35;
    // 第二个控制点为整个抛物线的中点  
    var q2x = startPoint.x + (endPoint.x - startPoint.x) * 0.65;

    var bezierConfig = {};
    bezierConfig.controlPoint_1 = cc.p(q1x, height + startPoint.y);
    bezierConfig.controlPoint_2 = cc.p(q2x, height + startPoint.y);
    bezierConfig.endPosition = cc.p(endPoint.x, endPoint.y);

    linePanel.bezier = bezierConfig;

    var footNum = Math.abs(endPoint.x - startPoint.x) / 25;
    var boatDelay = (footNum+1) * 0.2;
    var boatSailTime = 15 - boatDelay;
    for (var i = 0; i <= footNum; ++i) {
        var dt = i * (1.0 / footNum);
        var dt_next = (i + 1) * (1.0 / footNum);

        var curPos = this.getBezieratPos(startPoint, bezierConfig, dt);
        var nextPos = this.getBezieratPos(startPoint, bezierConfig, dt_next);

        var dirCur = cc.p(nextPos.x - curPos.x, nextPos.y - curPos.y);
        var normal = cc.p(1, 0);
        var angle = cc.pAngleSigned(dirCur, normal) / 3.1415926 * 180.0;

        var linePos = cc.p(curPos.x - startPoint.x, curPos.y - startPoint.y);
        var _line = this._lineOne.clone();
        _line.setPosition(linePos);
        _line.setRotation(angle);
        linePanel.addChild(_line, 10);
        _line.runAction(cc.Sequence.create(
            cc.DelayTime.create(i * 0.2),
            cc.Show.create(),
            cc.DelayTime.create(0.5+boatDelay+i*(boatSailTime/(footNum+1.0)-0.2)),
            cc.CallFunc.create( function (sender) {
                sender.loadTexture("res/ui/seaWorld/Route02.png");
            }, this)
        ));

        cc.log("pos line  : "+ i + "__"+linePos.x+"__"+linePos.y);
    }

    var boatBezierConfig = this.translateBezierWithRadian(startPoint, bezierConfig, -radian);
    this._mineBoatPanel.runAction(cc.Sequence.create(
        cc.DelayTime.create(boatDelay),
        cc.CallFunc.create( function (sender) {
            this._mineBoat.setFlippedX(flipx);
            this._mineBoat.effect.setVisible(true);
        }, this),
        cc.bezierTo(boatSailTime, [boatBezierConfig.controlPoint_1, boatBezierConfig.controlPoint_2, boatBezierConfig.endPosition]),
        cc.CallFunc.create( function (sender) {
            if (islast) {
                this._mineBoat.effect.setVisible(false);
                for (var i = 0; i < this._lineList.length; i++) {
                    this._lineList[i].removeFromParent();
                }
                this._lineList = [];
            }
            this.updateSailStatus(false);
        }, this)
    ));
},

然后要根据绘制曲线的中间x轴坐标计算曲线中的y轴坐标来绘制线段

getBezieratPos: function(startPoint, config, dt) {
    //bezierat( float a, float b, float c, float d, float t )
    var bezierConfig = {};
    bezierConfig.controlPoint_1 = cc.p(config.controlPoint_1.x - startPoint.x, config.controlPoint_1.y - startPoint.y);
    bezierConfig.controlPoint_2 = cc.p(config.controlPoint_2.x - startPoint.x, config.controlPoint_2.y - startPoint.y);
    bezierConfig.endPosition = cc.p(config.endPosition.x - startPoint.x , config.endPosition.y -startPoint.y);

    var xa = 0;
    var xb = bezierConfig.controlPoint_1.x;
    var xc = bezierConfig.controlPoint_2.x;
    var xd = bezierConfig.endPosition.x;

    var ya = 0;
    var yb = bezierConfig.controlPoint_1.y;
    var yc = bezierConfig.controlPoint_2.y;
    var yd = bezierConfig.endPosition.y;

    var x =  (Math.pow(1-dt,3) * xa + 3*dt*(Math.pow(1-dt,2))*xb + 3*Math.pow(dt,2)*(1-dt)*xc + Math.pow(dt,3)*xd );
    var y =  (Math.pow(1-dt,3) * ya + 3*dt*(Math.pow(1-dt,2))*yb + 3*Math.pow(dt,2)*(1-dt)*yc + Math.pow(dt,3)*yd );

    var ret_pot = cc.p(startPoint.x,startPoint.y);
    return cc.p(ret_pot.x + x , ret_pot.y + y);
},

最后船只要根据cc.bezierTo动作进行贝塞尔曲线移动,保证动作参数和绘制路线一致,动作参数boatBezierConfig需要根据起始点和转角进行转换

translateBezierWithRadian: function(startPoint, config, radian) {
    var boatBezierConfig = {};
    boatBezierConfig.controlPoint_1 = cc.p((config.controlPoint_1.x - startPoint.x)*Math.cos(radian) + startPoint.x - 150*Math.sin(radian), (config.controlPoint_1.x - startPoint.x)*Math.sin(radian) + startPoint.y + 150*Math.cos(radian));
    boatBezierConfig.controlPoint_2 = cc.p((config.controlPoint_2.x - startPoint.x)*Math.cos(radian) + startPoint.x - 150*Math.sin(radian), (config.controlPoint_2.x - startPoint.x)*Math.sin(radian) + startPoint.y + 150*Math.cos(radian));
    boatBezierConfig.endPosition = cc.p((config.endPosition.x - startPoint.x)*Math.cos(radian) + startPoint.x, (config.endPosition.x - startPoint.x)*Math.sin(radian) + startPoint.y);

    return boatBezierConfig;
},
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页