代码借鉴了论坛上的开源代码,完成的功能是摇杆控制角色移动,按钮可以自定义功能(代码里面有我自己写的一些功能,看懂了直接改代码就行),我设置的按钮最多有两个,有一些按钮是有蓄力功能,应该可以扩展。有问题可以在下方留言,希望大佬批评建议。
主要代码如下:
import JoystickCommon from 'JoystickCommon'
cc.Class({
extends: cc.Component,
properties: {
dot: {
default: null,
type: cc.Node,
displayName: 'Dot',
tooltip: '摇杆操纵点',
},
ring: {
default: null,
type: cc.Node,
displayName: 'Ring',
tooltip: '摇杆背景节点',
},
playerAllInfo: {
default: null,
type: cc.Node,
displayName: 'PlayerAllInfo',
tooltip: '操控角色',
},
haveButton_01:false,
button_01:{
type: cc.Node,
default: null,
tooltip: '右边第一按钮',
visible(){
return (this.haveButton_01===true);
}
},
haveButton_02:false,
button_02:{
type: cc.Node,
default: null,
tooltip: '右边第二按钮',
visible(){
return (this.haveButton_02===true);
}
},
_stickPos: {
default: null,
type: cc.Node,
tooltip: '摇杆所在位置',
},
_touchLocation: {
default: null,
type: cc.Node,
tooltip: '触摸位置',
},
_isThrow:false,
_isUpForTime:false,
_moveArray:[],
_moveIDArray:[],
_button_01Array:[],
_button_01IDArray:[],
_button_02Array:[],
_button_02IDArray:[],
width:0,
height:0,
},
//需要将父节点对象的大小设定为屏幕大小,并且在节点上加上wigth组件
onLoad() {
this.width=cc.winSize.width;
this.height=cc.winSize.height;
this.ring.setPosition(-this.width/2+235,-this.height/2+170);
this.dot.setPosition(-this.width/2+235,-this.height/2+170);
if(this.haveButton_02===false){
this.button_01.setPosition(this.width/2-235,-this.height/2+170);
}
else{
this.button_01.setPosition(this.width/2-120,-this.height/2+180);
this.button_02.setPosition(this.width/2-250,-this.height/2+80);
}
this._radius = this.ring.width / 2;
this._initTouchEvent();
this._playerAllInfo=this.playerAllInfo.getComponent("PlayerMove");
//固定摇杆位置
this._stickPos = this.ring.getPosition();
},
_initTouchEvent() {
const self = this;
self.node.on(cc.Node.EventType.TOUCH_START, self._touchStartEvent, self);
self.node.on(cc.Node.EventType.TOUCH_MOVE, self._touchMoveEvent, self);
self.node.on(cc.Node.EventType.TOUCH_END, self._touchEndEvent, self);
self.node.on(cc.Node.EventType.TOUCH_CANCEL, self._touchEndEvent, self);
},
_touchStartEvent(event) {
var startTouchNow=event.touch;
if(this.button_01.getBoundingBoxToWorld().contains(startTouchNow.getLocation())){
this._button_01Array.push(startTouchNow);
this._button_01IDArray.push(startTouchNow.getID());
}
else if( this.button_02!==null&&this.button_02.getBoundingBoxToWorld().contains(startTouchNow.getLocation())){
this._button_02Array.push(startTouchNow);
this._button_02IDArray.push(startTouchNow.getID());
}
else{
this._moveArray.push(startTouchNow);
this._moveIDArray.push(startTouchNow.getID());
}
//点击不同的右按钮进行相应的动作
if (this._button_01Array[0]&&this.button_01.getBoundingBoxToWorld().contains(this._button_01Array[0].getLocation())) {
this.button_01.opacity=255;
if(this.button_01.name==="Button_Up"){
this._playerAllInfo._Up=true;
}
else if(this.button_01.name==="Button_Sprint"){
this._playerAllInfo._Sprint=true;
}
else if(this.button_01.name==="Button_Long"){
this._playerAllInfo._long=true;
}
else if(this.button_01.name==="Button_ZhongQiuUp"){
this._playerAllInfo._ZhongQiuUp=true;
}
else if(this.button_01.name==="Button_UpForTime"){
this._isUpForTime=true;
this._playerAllInfo._upForTime=true;
}
}
if(this.button_02!==null){
if (this._button_02Array[0]&&this.button_02.getBoundingBoxToWorld().contains(this._button_02Array[0].getLocation())) {
if(this.haveButton_02===true){
this.button_02.opacity=255;
if(this.button_02.name==="Button_Throw"){
this._isThrow=true;
this._playerAllInfo._throw=true;
}
}
}
}
//End
//从世界坐标转换为节点坐标系
const touchPos = this.node.convertToNodeSpaceAR(this._moveArray[0].getLocation());
// 触摸点与圆圈中心的距离
const distance = touchPos.sub(this.ring.getPosition()).mag();
const p =cc.v2(touchPos.x,touchPos.y).sub(this.ring.getPosition()).normalize();
// 手指在圆圈内触摸,控杆跟随触摸点
if (this._radius > distance) {
this.dot.setPosition(touchPos);
}
else{
const x = this._stickPos.x + p.x * this._radius;
const y = this._stickPos.y + p.y * this._radius;
this.dot.setPosition(cc.v2(x, y));
}
this._playerAllInfo.moveDir = p;
this._playerAllInfo._speedType = JoystickCommon.SpeedType.NORMAL;
},
_touchMoveEvent(event) {
//判断点击的地方是不是在button对应的区域中,如果在button的区域中就不让左摇杆产生作用
if (this._button_01Array[0]&&this.button_01.getBoundingBoxToWorld().contains(this._button_01Array[0].getLocation())) {
if(this.haveButton_01===true){
this.button_01.opacity=255;
if(this.button_01.name==="Button_UpForTime"&&this._isUpForTime===true){
this._isUpForTime=true;
this._playerAllInfo._upForTime=true;
}
}
}
//如果在移动过程中移出了按钮的范围,就直接结束计时
if(this.button_02!==null){
if (this._button_02Array[0]&&this.button_02.getBoundingBoxToWorld().contains(this._button_02Array[0].getLocation())) {
this.button_02.opacity=255;
if(this.button_02.name==="Button_Throw"&&this._isThrow){
this._playerAllInfo._throw=true;
}
}
else if(this._button_02Array[0]&&!this.button_02.getBoundingBoxToWorld().contains(this._button_02Array[0].getLocation())&&this._isThrow){
this.button_01.opacity=128;
this.button_02.opacity=128;
this._playerAllInfo._throw=false;
this._isThrow=false;
}
}
//End
// 以圆圈为锚点获取触摸坐标
if(this._moveArray[0]){
const touchPos = this.ring.convertToNodeSpaceAR(this._moveArray[0].getLocation());
const distance = touchPos.mag();
// 由于摇杆的 postion 是以父节点为锚点,所以定位要加上 touch start 时的位置
const posX = this._stickPos.x + touchPos.x;
const posY = this._stickPos.y + touchPos.y;
// 归一化
const p = cc.v2(posX, posY).sub(this.ring.getPosition()).normalize();
if (this._radius > distance) {
this.dot.setPosition(cc.v2(posX, posY));
} else {
// 控杆永远保持在圈内,并在圈内跟随触摸更新角度
const x = this._stickPos.x + p.x * this._radius;
const y = this._stickPos.y + p.y * this._radius;
this.dot.setPosition(cc.v2(x, y));
}
//向Player对象传递方向
this._playerAllInfo.moveDir = p;
//想Player对象传递速度
this._playerAllInfo._speedType = JoystickCommon.SpeedType.NORMAL;
}
},
_touchEndEvent(event) {
if(this.button_01!==null){
this.button_01.opacity=128;
if(this.button_01.name==="Button_UpForTime"){
this._isUpForTime=false;
this._playerAllInfo._upForTime=false;
}
}
if(this.button_02!==null){
this.button_02.opacity=128;
if(this.button_02.name==="Button_Throw"){
this._isThrow=false;
this._playerAllInfo._throw=false;
}
}
//如果是中秋或者重阳节,那么玩家松开摇杆的默认方向是0,0
if(cc.director.getScene().name==="Festival_ZhongQiu"||cc.director.getScene().name==="Festival_ChongYang"){
this._playerAllInfo.moveDir=cc.v2(0,0);
}
this._playerAllInfo._speedType = JoystickCommon.SpeedType.STOP;
//如果手指结束触摸了,就从三个数组中找到这个手指的信息并删除
for (let i = 0; i < this._moveIDArray.length; i++) {
if (this._moveIDArray[i]===event.touch.getID()) {
this._moveArray.splice(i,1);
this._moveArray.splice(i,1);
if(this._moveArray.length===0){
this.dot.setPosition(this.ring.getPosition());
}
}
}
for (let i = 0; i < this._button_01IDArray.length; i++) {
if (this._button_01IDArray[i]===event.touch.getID()) {
this._button_01Array.splice(i,1);
this._button_01Array.splice(i,1);
}
}
for (let i = 0; i < this._button_02IDArray.length; i++) {
if (this._button_02IDArray[i]===event.touch.getID()) {
this._button_02Array.splice(i,1);
this._button_02Array.splice(i,1);
}
}
},
});
JoystickCommon代码如下:
export default {
SpeedType: cc.Enum({
STOP: 0,
NORMAL: 1
}),
};