我们要分析的就是cocos create 官方给出的那个机器人,如何完成瞄准触摸点并不断随着触摸点进行动作更新动作。
实际上机器人关于转向的只有向上和向下瞄准这两个动作。
完成丰富的转向动作考靠的是动画的weight属性,这个变量时控制本龙骨某个动画动作幅度的一个属性,我们可以通过改变它来改变动作的幅度,取值是[0,1]。
具体的操作如下面的代码(ps:这段代码加载龙骨节点下面):
// 获取龙骨的属性
this._armatureDisplay = this.getComponent(dragonBones.ArmatureDisplay);
this._armature = this._armatureDisplay.armature();
// 播放要播放的动画,并声明变量记录播放动画函数的返回值
this._aimState = this._armature.animation.fadeIn(
"aimUp", 0, 1,
0, "aim", 2
);
//|||||||||||||||||||||||||||||||||||
//下面是关键!!!
//这里既是改变动作幅度的方法,通过给weight赋值
//来改变举枪的动作!!!
this._aimState.weight=0.2;
执行代码的效果如下:
我们发现这个机器值进行的原来动作幅度的0.2,只是上举了一小点儿。这既是完成这些动作的核心。
完整的不断对触摸点瞄准的动作就是基于这个原理来完成。首先通过Math.atan2()函数,以机器人为原点,触摸点为坐标的夹角的值R(这个是我自己设的变量),并把值R按比例转换为0到1之间。最后在update()函数中不断调用,把值R赋给weight,就完成了机器的武器的转向了。
完整的跟随触摸点变化的代码如下(要加在机器人的节点下面):
cc.Class({
extends: cc.Component,
properties: {
touchHandler:{
default:null,
type:cc.Node,
},
_aimDir:0,
_aimRadian:0,
_aimState : null,
_target : cc.v2(0, 0),
},
// LIFE-CYCLE CALLBACKS:
onLoad () {
this.touchHandler.on(cc.Node.EventType.TOUCH_START, event => {
var touches = event.getTouches();
var touchLoc = touches[0].getLocation();
this.aim(touchLoc.x, touchLoc.y);
//this.attack(true);
}, this);
this.touchHandler.on(cc.Node.EventType.TOUCH_END, event => {
//this.attack(false);
}, this);
this.touchHandler.on(cc.Node.EventType.TOUCH_MOVE, event => {
var touches = event.getTouches();
var touchLoc = touches[0].getLocation();
this.aim(touchLoc.x, touchLoc.y);
}, this);
},
start() {
this._armatureDisplay = this.getComponent(dragonBones.ArmatureDisplay);
this._armature = this._armatureDisplay.armature();
},
/**
* 获取瞄准目标
*/
aim(x,y){
if (this._aimDir === 0) {
this._aimDir = 10;
}
this._target = this.node.parent.convertToNodeSpaceAR(cc.v2(x, y));
},
update (dt) {
this._updateAim();
},
_updateAim () {
if (this._aimDir === 0) {
return;
}
//决定机器人开火的Y轴方向
this._faceDir = this._target.x > this.node.x ? 1 : -1;
//通过改变机器人的scaleX的数值来对机器人的转身进行改变
if (this.node.scaleX * this._faceDir < 0) {
this.node.scaleX *= -1;
if (this._moveDir) {
this._updateAnimation();
}
}
//获取胸部骨骼的世界坐标
//var global = this._armature.getBone("chest").global;
var aimOffsetY = this._armature.getBone("chest").global.y ;//* this.node.scaleY;
//var bonePos = this.node.parent.convertToNodeSpaceAR(cc.v2(global.x, global.y));
//cc.log(this._target.y-bonePos.y,this._target.x-bonePos.x);
//获取夹角的值
if (this._faceDir > 0) {
this._aimRadian = Math.atan2((this._target.y - this.node.y + aimOffsetY), this._target.x - this.node.x);
} else {
this._aimRadian = Math.PI - Math.atan2((this._target.y - this.node.y + aimOffsetY), this._target.x - this.node.x);
if (this._aimRadian > Math.PI) {
this._aimRadian -= Math.PI * 2;
}
}
let aimDir = 0;
if (this._aimRadian < 0) {
aimDir = -1;
} else {
aimDir = 1;
}
if (this._aimDir != aimDir) {
this._aimDir = aimDir;
// Animation mixing.
if (this._aimDir >= 0) {
this._aimState = this._armature.animation.fadeIn(
"aimUp", 0, 1,
0, "normal", 2
);
} else {
this._aimState = this._armature.animation.fadeIn(
"aimDown", 0, 1,
0, "normal", 2
);
}
// Add bone mask.
//_aimState.addBoneMask("pelvis");
}
this._aimState.weight = Math.abs(this._aimRadian / Math.PI * 2);
//_armature.invalidUpdate("pelvis"); // Only update bone mask.
this._armature.invalidUpdate();
},
});