在竖版rpg游戏中常常需要摇杆来控制角色移动。我们这里给出在laya引擎中一个摇杆的简单实现。用户只需要在UI界面简单的设置一个摇杆的触摸区、摇杆bg和摇杆柄即可。如下图所示
import Script = Laya.Script;
import Image = Laya.Image;
import Event = Laya.Event;
import Sprite = Laya.Sprite;
import Point = Laya.Point;
/** 摇杆半径 */
export const JoystickRadius: number = 64;
export default class Joystick extends Script {
/** 可触摸区域节点 */
private _touchAreaSpr: Sprite;
/** 摇杆背景 */
private _joystickBg: Image;
/** 摇杆的柄 */
private _joystickHandler: Image;
/** 是否按下摇杆的柄 */
private _isPressHandler: boolean = false;
/** 摇杆的中心点 */
private _centerPoint: Point = new Point();
/** 摇杆柄的局部位置 */
private _localPoint: Point = new Point();
/** 摇杆柄的局部位置相对于stage在水平方向上的增量 */
private _deltaX: number = 0;
private _deltaY: number = 0;
// /** 摇杆角度 0 - 360*/
// public static JoyAngle: number = -1;
/** 摇杆方向, 包含尺度(0 - 1) */
public static JoyDir: Point = new Point();
onAwake(): void {
this._touchAreaSpr = this.owner.parent as Sprite;
this._joystickBg = this.owner as Image;
this._joystickHandler = this.owner.getChildAt(0) as Image;
}
onEnable(): void {
// this._joystickHandler.on(Event.MOUSE_DOWN, this, this.onMouseDownHandler);
this._touchAreaSpr.on(Event.MOUSE_DOWN, this, this.onBgMouseDown);
this._touchAreaSpr.on(Event.MOUSE_MOVE, this, this.onBgMouseMove);
this._touchAreaSpr.on(Event.MOUSE_UP, this, this.onBgMouseUp);
this._touchAreaSpr.on(Event.MOUSE_OUT, this, this.onBgMouseUp);
this._centerPoint.setTo(this._joystickBg.pivotX, this._joystickBg.pivotY);
}
onDisable(): void {
this._joystickHandler.offAll();
this._touchAreaSpr.offAll();
}
// /** 鼠标按下摇杆柄部 */
// private onMouseDownHandler() {
// this._isPressHandler = true;
// }
private onBgMouseDown(e: Event): void {
if(this._isPressHandler) return;
this._isPressHandler = true;
this._joystickBg.pos(e.stageX, e.stageY - this._touchAreaSpr.y); // 让摇杆追随玩家手指
this._deltaX = this._touchAreaSpr.x + this._joystickBg.x - this._joystickBg.pivotX;
this._deltaY = this._touchAreaSpr.y + this._joystickBg.y - this._joystickBg.pivotY;
this._joystickBg.set_visible(true);
}
private onBgMouseMove(e: Event): void {
if (!this._isPressHandler) return;
/** 移动摇杆柄 */
this._localPoint.x = e.stageX - this._deltaX;
this._localPoint.y = e.stageY - this._deltaY;
if (this.distance(this._localPoint, this._centerPoint) > JoystickRadius) { // 超过摇杆半径时处理
this._localPoint.setTo(this._localPoint.x - this._centerPoint.x, this._localPoint.y - this._centerPoint.y);
this._localPoint.normalize();
Joystick.JoyDir.copy(this._localPoint);
this._localPoint.setTo(this._centerPoint.x + this._localPoint.x * JoystickRadius, this._centerPoint.y + this._localPoint.y * JoystickRadius);
} else {
Joystick.JoyDir.setTo((this._localPoint.x - this._centerPoint.x) / JoystickRadius, (this._localPoint.y - this._centerPoint.y) / JoystickRadius);
}
this._joystickHandler.pos(this._localPoint.x, this._localPoint.y);
}
private onBgMouseUp(e: Event): void {
if (!this._isPressHandler) return;
this._isPressHandler = false;
this._joystickBg.pos(this._touchAreaSpr.width / 2, this._touchAreaSpr.height / 2);
this._joystickHandler.pos(this._centerPoint.x, this._centerPoint.y);
Joystick.JoyDir.reset();
this._joystickBg.set_visible(false);
}
private distance(p1:Point, p2:Point): number {
return Math.sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
}
}