Cocos Creator 封装圆周动作


前言

cocos creator内封装了很多方便使用的动作供大家使用,例如moveBy、moveTo、rotateBy、rotateTo等,但是也有一些特殊的动作没法实现,比如本文即将展现给大家的圆周运动。


一、先上效果图?

在这里插入图片描述

二、设计思路

    // 圆周运动继承于cc.ActionInterval,属于时间间隔动作;
    // 圆周运动是根据持续时间、圆心位置、半径、初始角度以及旋转角度五种属性来实现;
    // 当前坐标公式:
    // let x = radius * Math.sin((angle / 180) * Math.PI);
    // let y = radius * Math.cos((angle / 180) * Math.PI);
    // 设计传入参数 为 duration(时间), deltaAngle(旋转角度或旋转到角度), deltaPos(圆心位置或圆心位置x坐标), deltaY(圆心位置y坐标)
    // 设计中未加入初始角度(原因1:减少传入值,方便使用;2:一般来说圆周运动开始前都会设置好节点的开始位置和开始角度,没必要在做处理;)
    // 如果以上不能满足需求,也可增加初始角度(具体实现可查看moveCircle.js,对this._startAngle重新赋值)
    // 需要注意的是: 设计中未加入初始角度,在开始执行动作时,会根据当前节点角度,改变节点位置.如果要实现动作与实际不符,可关注此条!!!
    // 设计参考 官方 cc.rotateTo、cc.rotateBy;
    // 参考地址 https://github.com/cocos-creator/engine/blob/26031bddd1aecdbf9bbdebe19ecaa672b1c35061/cocos2d/actions/CCActionInterval.js#L1144

三、实现

1. moveCircleBy

cc.MoveCircleBy = cc.Class({
    name: 'cc.MoveCircleBy',
    extends: cc.ActionInterval,

    statics: {
        _reverse: false,
    },

    ctor: function (duration, deltaAngle, deltaPos, deltaY) {
        // 半径
        this._radius = 0;
        // 目标角度
        this._deltaAngle = 0;
        // 开始角度
        this._startAngle = 0;
        // 开始位置
        this._startPosition = cc.v2(0, 0);
        // 圆心位置
        this._centerPosition = cc.v2(0, 0);

        if (deltaAngle !== undefined) {
            deltaAngle *= cc.MoveCircleBy._reverse ? 1 : -1;
            this.initWithDuration(duration, deltaAngle, deltaPos, deltaY);
        }
    },

    // Initializes the action.
    initWithDuration: function (duration, deltaAngle, deltaPos, deltaY) {
        if (cc.ActionInterval.prototype.initWithDuration.call(this, duration, deltaPos, deltaY)) {
            this._deltaAngle = deltaAngle;
            if (deltaPos.x !== undefined) {
                deltaY = deltaPos.y;
                deltaPos = deltaPos.x;
            }
            this._centerPosition.x = deltaPos;
            this._centerPosition.y = deltaY;
            return true;
        }
        return false;
    },

    clone: function () {
        var action = new cc.MoveCircleBy();
        this._cloneDecoration(action);
        action.initWithDuration(this._duration, this._deltaAngle, this._centerPosition);
        return action;
    },

    startWithTarget: function (target) {
        cc.ActionInterval.prototype.startWithTarget.call(this, target);
        this._startAngle = target.angle;

        this._startPosition.x = target.x;
        this._startPosition.y = target.y;
        this._radius = dist(this._centerPosition, this._startPosition);
    },

    update: function (dt) {
        dt = this._computeEaseTime(dt);
        if (this.target) {
            // cc.log(this._deltaAngle * dt);

            // 根据半径和弧度求出圆一点坐标
            let x = -this._radius * Math.sin(((this._startAngle + this._deltaAngle * dt) / 180) * Math.PI);
            let y = this._radius * Math.cos(((this._startAngle + this._deltaAngle * dt) / 180) * Math.PI);
            // 更新坐标
            this.target.x = this._centerPosition.x + x;
            this.target.y = this._centerPosition.y + y;
            this.target.angle = this._startAngle + this._deltaAngle * dt;
        }
    },

    reverse: function () {
        var action = new cc.MoveCircleBy();
        action.initWithDuration(this._duration, -this._deltaAngle, this._centerPosition);
        this._cloneDecoration(action);
        this._reverseEaseList(action);
        return action;
    },
});

/**
 * !#zh 顺时针移动,旋转指定的角度。
 * @method moveCircleBy
 * @param {Number} duration duration in seconds
 * @param {Number} deltaAngle deltaAngle in degrees
 * @param {Vec2|Number} deltaPos deltaPos in center position
 * @param {Number} [deltaY]
 * @return {ActionInterval}
 * @example
 * example
 * var actionBy = new cc.MoveCircleBy(2, 360, cc.v(0, 0));
 */
cc.moveCircleBy = function (duration, deltaAngle, deltaPos, deltaY) {
    return new cc.MoveCircleBy(duration, deltaAngle, deltaPos, deltaY);
};

2. moveCircleTo

cc.MoveCircleTo = cc.Class({
    name: 'cc.MoveCircleTo',
    extends: cc.ActionInterval,

    statics: {
        _reverse: false,
    },

    ctor: function (duration, dstAngle, deltaPos, deltaY) {
        this._angle = 0;
        this._radius = 0;
        this._dstAngle = 0;
        this._startAngle = 0;
        this._startPosition = cc.v2(0, 0);
        this._centerPosition = cc.v2(0, 0);

        dstAngle !== undefined && this.initWithDuration(duration, dstAngle, deltaPos, deltaY);
    },

    // Initializes the action.
    initWithDuration: function (duration, dstAngle, deltaPos, deltaY) {
        if (cc.ActionInterval.prototype.initWithDuration.call(this, duration)) {
            this._dstAngle = dstAngle;
            if (deltaPos.x !== undefined) {
                deltaY = deltaPos.y;
                deltaPos = deltaPos.x;
            }
            this._centerPosition.x = deltaPos;
            this._centerPosition.y = deltaY;
            return true;
        }
        return false;
    },

    clone: function () {
        var action = new cc.MoveCircleTo();
        this._cloneDecoration(action);
        action.initWithDuration(this._duration, this._dstAngle, this._centerPosition);
        return action;
    },

    startWithTarget: function (target) {
        cc.ActionInterval.prototype.startWithTarget.call(this, target);
        let startAngle = target.angle % 360;
        let angle = cc.MoveCircleTo._reverse ? this._dstAngle - startAngle : this._dstAngle + startAngle;
        if (angle > 180) angle -= 360;
        if (angle < -180) angle += 360;
        this._startAngle = startAngle;
        this._angle = cc.MoveCircleTo._reverse ? angle : -angle;

        this._startPosition.x = target.x;
        this._startPosition.y = target.y;
        this._radius = dist(this._centerPosition, this._startPosition);
    },

    reverse: function () {
        cc.logID(1016);
    },

    update: function (dt) {
        dt = this._computeEaseTime(dt);
        if (this.target) {
            this.target.angle = this._startAngle + this._angle * dt;

            // cc.log(this._angle * dt);
            // 根据半径和弧度求出圆一点坐标
            let x = -this._radius * Math.sin(((this._startAngle + this._angle * dt) / 180) * Math.PI);
            let y = this._radius * Math.cos(((this._startAngle + this._angle * dt) / 180) * Math.PI);
            // 更新坐标
            this.target.x = this._centerPosition.x + x;
            this.target.y = this._centerPosition.y + y;
        }
    },
});

/**
 * !#zh 旋转到目标角度,通过逐帧修改它的 angle 属性,旋转方向将由最短的角度决定。
 * @method rotateTo
 * @param {Number} duration duration in seconds
 * @param {Number} dstAngle dstAngle in degrees.
 * @param {Vec2|Number} deltaPos deltaPos in center position
 * @param {Number} [deltaY]
 * @return {ActionInterval}
 * @example
 * example
 * var actionTo = new cc.moveCircleTo(2, 360, cc.v(0, 0));
 */
cc.moveCircleTo = function (duration, dstAngle, deltaPos, deltaY) {
    return new cc.MoveCircleTo(duration, dstAngle, deltaPos, deltaY);
};

四、使用

1.引入moveCircle.js 到cocos creator设置为插件

2.具体使用

        // 与普通动作使用方式一样
        let moveCircleBy = cc.moveCircleBy(10, 360, 0, 0);
        // let moveCircleTo = cc.moveCircleBy(10, 360, 0, 0);
        this.node.runAction(moveCircleBy);

总结

以上就是我的实现思路!!!希望对大家有用!
最后为大家附上源码!!! CSDN下载地址 码云Gitee下载地址

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值