关于CocosCreator知识库<二>_JavaScript的虚拟摇杆的通用模板_全方向_八个方向_四个方向<25/12/2017>
首先,上实际图效果:
先介绍demo层级管理器的分配:
上全所有脚本,如下:
Joystick脚本:
var Common = require('JoystickBar');
var JoystickBG = require('JoystickBG');
cc.Class({
extends: cc.Component,
properties: {
dot: {
default: null,
type: cc.Node,
displayName: '摇杆节点',
},
ring: {
default: null,
type: JoystickBG,
displayName: '摇杆背景节点',
},
stickX: {
default: 0,
displayName: '摇杆X位置',
},
stickY: {
default: 0,
displayName: '摇杆Y位置',
},
touchType: {
default: Common.TouchType.DEFAULT,
type: Common.TouchType,
displayName: '触摸类型',
},
directionType: {
default: Common.DirectionType.ALL,
type: Common.DirectionType,
displayName: '方向类型',
},
sprite: {
default: null,
type: cc.Node,
displayName: '操控的目标',
},
_stickPos: {
default: null,
type: cc.Node,
displayName: '摇杆当前位置',
},
_touchLocation: {
default: null,
type: cc.Node,
displayName: '摇杆当前位置',
}
},
onLoad: function () {
this._createStickSprite();
//当触摸类型为FOLLOW会在此对圆圈的触摸监听
if (this.touchType == Common.TouchType.FOLLOW) {
this._initTouchEvent();
}
},
_createStickSprite: function () {
//调整摇杆的位置
this.ring.node.setPosition(this.stickX, this.stickY);
this.dot.setPosition(this.stickX, this.stickY);
},
_initTouchEvent: function () {
var self = this;
self.node.on(cc.Node.EventType.TOUCH_START, self._touchStartEvent, self);
self.node.on(cc.Node.EventType.TOUCH_MOVE, self._touchMoveEvent, self);
// 触摸在圆圈内离开或在圆圈外离开后,摇杆归位,player速度为0
self.node.on(cc.Node.EventType.TOUCH_END, self._touchEndEvent, self);
self.node.on(cc.Node.EventType.TOUCH_CANCEL, self._touchEndEvent, self);
},
_touchStartEvent: function (event) {
// 记录触摸的世界坐标,给touch move使用
this._touchLocation = event.getLocation();
var touchPos = this.node.convertToNodeSpaceAR(event.getLocation());
// 更改摇杆的位置
this.ring.node.setPosition(touchPos);
this.dot.setPosition(touchPos);
// 记录摇杆位置,给touch move使用
this._stickPos = touchPos;
},
_touchMoveEvent: function (event) {
// 如果touch start位置和touch move相同,禁止移动
if (this._touchLocation.x == event.getLocation().x && this._touchLocation.y == event.getLocation().y) {
return false;
}
// 以圆圈为锚点获取触摸坐标
var touchPos = this.ring.node.convertToNodeSpaceAR(event.getLocation());
var distance = this.ring._getDistance(touchPos, cc.p(0, 0));
var radius = this.ring.node.width / 2;
// 由于摇杆的postion是以父节点为锚点,所以定位要加上touch start时的位置
var posX = this._stickPos.x + touchPos.x;
var posY = this._stickPos.y + touchPos.y;
if (radius > distance) {
this.dot.setPosition(cc.p(posX, posY));
} else {
//控杆永远保持在圈内,并在圈内跟随触摸更新角度
var x = this._stickPos.x + Math.cos(this.ring._getRadian(cc.p(posX, posY))) * radius;
var y = this._stickPos.y + Math.sin(this.ring._getRadian(cc.p(posX, posY))) * radius;
this.dot.setPosition(cc.p(x, y));
}
//更新角度
this.ring._getAngle(cc.p(posX, posY));
//设置实际速度
this.ring._setSpeed(cc.p(posX, posY));
},
_touchEndEvent: function () {
this.dot.setPosition(this.ring.node.getPosition());
this.ring._speed = 0;
},
});
JoystickBar脚本:
module.exports = {
TouchType : cc.Enum({
DEFAULT: 0,
FOLLOW: 1,
}),
DirectionType : cc.Enum({
FOUR: 4,
EIGHT: 8,
ALL: 0,
}),
};
JoystickBG脚本:
var Common = require('JoystickBar');
cc.Class({
extends: cc.Component,
properties: {
dot: {
default: null,
type: cc.Node,
displayName: '摇杆节点',
},
_joyCom: {
default: null,
displayName: 'joy Node',
},
_playerNode: {
default: null,
displayName: '被操作的目标Node',
},
_angle: {
default: null,
displayName: '当前触摸的角度',
},
_radian: {
default: null,
displayName: '弧度',
},
_speed: 0, //实际速度
_speed1: 1, //一段速度
_speed2: 2, //二段速度
_opacity: 0, //透明度
},
onLoad: function () {
// joy下的Joystick组件
this._joyCom = this.node.parent.getComponent('Joystick');
// Joystick组件下的player节点
this._playerNode = this._joyCom.sprite;
if (this._joyCom.touchType == Common.TouchType.DEFAULT) {
//对圆圈的触摸监听
this._initTouchEvent();
}
},
//对圆圈的触摸监听
_initTouchEvent: function () {
var self = this;
self.node.on(cc.Node.EventType.TOUCH_START, this._touchStartEvent, self);
self.node.on(cc.Node.EventType.TOUCH_MOVE, this._touchMoveEvent, self);
// 触摸在圆圈内离开或在圆圈外离开后,摇杆归位,player速度为0
self.node.on(cc.Node.EventType.TOUCH_END, this._touchEndEvent, self);
self.node.on(cc.Node.EventType.TOUCH_CANCEL, this._touchEndEvent, self);
},
//更新移动目标
update: function (dt) {
switch (this._joyCom.directionType) {
case Common.DirectionType.FOUR:
this._fourDirectionsMove();
break;
case Common.DirectionType.EIGHT:
this._eightDirectionsMove();
break;
case Common.DirectionType.ALL:
this._allDirectionsMove();
break;
default:
break;
}
},
//四个方向移动(上下左右)
_fourDirectionsMove: function () {
if (this._angle > 45 && this._angle < 135) {
this._playerNode.y += this._speed;
} else if (this._angle > -135 && this._angle < -45) {
this._playerNode.y -= this._speed;
} else if (this._angle < -135 && this._angle > -180 || this._angle > 135 && this._angle < 180) {
this._playerNode.x -= this._speed;
} else if (this._angle < 0 && this._angle > -45 || this._angle > 0 && this._angle < 45) {
this._playerNode.x += this._speed;
}
},
//八个方向移动(上下左右、左上、右上、左下、右下)
_eightDirectionsMove: function () {
if (this._angle > 67.5 && this._angle < 112.5) {
this._playerNode.y += this._speed;
} else if (this._angle > -112.5 && this._angle < -67.5) {
this._playerNode.y -= this._speed;
} else if (this._angle < -157.5 && this._angle > -180 || this._angle > 157.5 && this._angle < 180) {
this._playerNode.x -= this._speed;
} else if (this._angle < 0 && this._angle > -22.5 || this._angle > 0 && this._angle < 22.5) {
this._playerNode.x += this._speed;
} else if (this._angle > 112.5 && this._angle < 157.5) {
this._playerNode.x -= this._speed / 1.414;
this._playerNode.y += this._speed / 1.414;
} else if (this._angle > 22.5 && this._angle < 67.5) {
this._playerNode.x += this._speed / 1.414;
this._playerNode.y += this._speed / 1.414;
} else if (this._angle > -157.5 && this._angle < -112.5) {
this._playerNode.x -= this._speed / 1.414;
this._playerNode.y -= this._speed / 1.414;
} else if (this._angle > -67.5 && this._angle < -22.5) {
this._playerNode.x += this._speed / 1.414;
this._playerNode.y -= this._speed / 1.414;
}
},
//全方向移动
_allDirectionsMove: function () {
this._playerNode.x += Math.cos(this._angle * (Math.PI / 180)) * this._speed;
this._playerNode.y += Math.sin(this._angle * (Math.PI / 180)) * this._speed;
},
//计算两点间的距离并返回
_getDistance: function (pos1, pos2) {
return Math.sqrt(Math.pow(pos1.x - pos2.x, 2) +
Math.pow(pos1.y - pos2.y, 2));
},
/*角度/弧度转换
角度 = 弧度 * 180 / Math.PI
弧度 = 角度 * Math.PI / 180*/
//计算弧度并返回
_getRadian: function (point) {
this._radian = Math.PI / 180 * this._getAngle(point);
return this._radian;
},
//计算角度并返回
_getAngle: function (point) {
var pos = this.node.getPosition();
this._angle = Math.atan2(point.y - pos.y, point.x - pos.x) * (180 / Math.PI);
return this._angle;
},
//设置实际速度
_setSpeed: function (point) {
//触摸点和遥控杆中心的距离
var distance = this._getDistance(point, this.node.getPosition());
//如果半径
if (distance < this._radius) {
this._speed = this._speed1;
} else {
this._speed = this._speed2;
}
},
_touchStartEvent: function (event) {
// 获取触摸位置的世界坐标转换成圆圈的相对坐标(以圆圈的锚点为基准)
var touchPos = this.node.convertToNodeSpaceAR(event.getLocation());
//触摸点与圆圈中心的距离
var distance = this._getDistance(touchPos, cc.p(0, 0));
//圆圈半径
var radius = this.node.width / 2;
// 记录摇杆位置,给touch move使用
this._stickPos = touchPos;
var posX = this.node.getPosition().x + touchPos.x;
var posY = this.node.getPosition().y + touchPos.y;
//手指在圆圈内触摸,控杆跟随触摸点
if (radius > distance) {
this.dot.setPosition(cc.p(posX, posY));
return true;
}
return false;
},
_touchMoveEvent: function (event) {
var touchPos = this.node.convertToNodeSpaceAR(event.getLocation());
var distance = this._getDistance(touchPos, cc.p(0, 0));
var radius = this.node.width / 2;
// 由于摇杆的postion是以父节点为锚点,所以定位要加上ring和dot当前的位置(stickX,stickY)
var posX = this.node.getPosition().x + touchPos.x;
var posY = this.node.getPosition().y + touchPos.y;
if (radius > distance) {
this.dot.setPosition(cc.p(posX, posY));
} else {
//控杆永远保持在圈内,并在圈内跟随触摸更新角度
var x = this.node.getPosition().x + Math.cos(this._getRadian(cc.p(posX, posY))) * radius;
var y = this.node.getPosition().y + Math.sin(this._getRadian(cc.p(posX, posY))) * radius;
this.dot.setPosition(cc.p(x, y));
}
//更新角度
this._getAngle(cc.p(posX, posY));
//设置实际速度
this._setSpeed(cc.p(posX, posY));
},
_touchEndEvent: function () {
this.dot.setPosition(this.node.getPosition());
this._speed = 0;
},
});