文章目录
前言
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下载地址