前面一篇文章写了几种常见的主角控制方式,这篇文章将介绍 利用摇杆JoyStick 去控制主角。
看到网上都是JS写的代码,找了一个效果不错的参考了一下,本文采用TS写的:
首先查看效果图:
摇杆有两种显示方式,都是平时在游戏里常见的。
实现起来 和Unity 里面 的摇杆实现方式差不多,只是语言不同罢了。
首先是 摇杆类:
onLoad()
{
this.radius=this.bgNode.width/2;
this.initTouchEvent();
if (this.joyStickType==JoyStickType.FOLLOW)
{
this.node.opacity=0;
}
this.playerScr=this.player.getComponent('Player');
}
initTouchEvent()
{
this.node.on(cc.Node.EventType.TOUCH_START,this.touchStartEvent,this);
this.node.on(cc.Node.EventType.TOUCH_MOVE,this.touchMoveEvent,this);
this.node.on(cc.Node.EventType.TOUCH_END,this.touchEndEvent,this);
this.node.on(cc.Node.EventType.TOUCH_CANCEL,this.touchEndEvent,this);
}
touchStartEvent(event)
{
let startTouchPos=this.node.convertToNodeSpaceAR(event.getLocation());
if(this.joyStickType==JoyStickType.FIXED)
{
this.stickPos=this.bgNode.getPosition();
let distance=startTouchPos.sub(this.bgNode.getPosition()).mag();
if(this.radius>distance)
{
this.dotNode.setPosition(startTouchPos);
}
}
else if(this.joyStickType==JoyStickType.FOLLOW)
{
this.stickPos=startTouchPos;
this.node.opacity=255;
this.touchPos=event.getLocation();
this.bgNode.setPosition(startTouchPos);
this.dotNode.setPosition(startTouchPos);
}
}
touchMoveEvent(event)
{
if(this.joyStickType==JoyStickType.FOLLOW)
{
if(this.touchPos==event.getLocation())
{
return;
}
}
//将触摸坐标 转化到 bg 下, 此时 的dis 就是 触摸点相对于bg 的距离
let touchP=this.bgNode.convertToNodeSpaceAR(event.getLocation());
let dis=touchP.mag();
let posX=this.stickPos.x+touchP.x;
let posY=this.stickPos.y+touchP.y;
//向量归一(获取方向)
let p = cc.v2(posX,posY).sub(this.bgNode.getPosition()).normalize();
if(this.radius>dis)
{
this.dotNode.setPosition(cc.v2(posX,posY));
this.playerScr.speedType=SpeedType.NORMAL;
}
else
{
//摇杆在圈边
let nowPosX=this.stickPos.x+p.x*this.radius;
let nowPosy=this.stickPos.y+p.y*this.radius;
this.dotNode.setPosition(cc.v2(nowPosX,nowPosy));
this.playerScr.speedType=SpeedType.FAST;
}
this.playerScr.moveDir=p;
}
touchEndEvent(event)
{
this.dotNode.setPosition(this.bgNode.getPosition());
if(this.joyStickType==JoyStickType.FOLLOW)
{
this.node.opacity=0;
}
this.playerScr.speedType=SpeedType.STOP;
}
onDestroy()
{
this.node.off(cc.Node.EventType.TOUCH_START,this.touchStartEvent,this);
this.node.off(cc.Node.EventType.TOUCH_MOVE,this.touchMoveEvent,this);
this.node.off(cc.Node.EventType.TOUCH_END,this.touchEndEvent,this);
this.node.off(cc.Node.EventType.TOUCH_CANCEL,this.touchEndEvent,this);
}
也是几种触摸事件结合实现的。
接着是player 类的实现:
//移动方向
moveDir=cc.v2(0,1);
moveSpeed:number=0;
stopSpeed:number=0;
normalSpeed:number=100;
fastSpeed:number=200;
update(dt)
{
switch(this.speedType)
{
case SpeedType.STOP:
this.moveSpeed=this.stopSpeed;
break;
case SpeedType.NORMAL:
this.moveSpeed=this.normalSpeed;
break;
case SpeedType.FAST:
this.moveSpeed=this.fastSpeed;
break;
}
this.move();
}
move()
{
//radiansToDegrees弧度转角度。atan2返回从 x 轴到点 (x,y) 之间的角度 Math.atan2(y,x),结果为弧度
this.node.rotation=90-cc.misc.radiansToDegrees(Math.atan2(this.moveDir.y,this.moveDir.x));
//缩放向量
let newPos=this.node.position.add(this.moveDir.mul(this.moveSpeed/60));
this.node.setPosition(newPos);
}
具体demo 链接:https://download.csdn.net/download/hnzmdlhc/11253948
附上enum 脚本:
export enum SpeedType
{
STOP,
NORMAL,
FAST,
}
export enum JoyStickType
{
FIXED,
FOLLOW,
}
export enum DirectionType
{
FOUR,
EIGHT,
ALL,
}