
在很多手机游戏中,虚拟摇杆是移动控制的常见方案,尤其是在动作类、冒险类游戏中非常实用。今天我使用 Cocos Creator 3.8.6 版本,通过一段简洁的 TypeScript 脚本,手把手教大家如何实现一个基础的虚拟摇杆功能。

虚拟摇杆主要包含两个关键节点:
功能逻辑:
虚拟摇杆图片素材下载 https://wlor.lanzoum.com/itwAB32zngje
Joystick。
Joystick 下创建两个子节点:
joystickBg (摇杆背景)joystickHandle (摇杆柄)joystickBg 和 joystickHandle 节点添加合适的图片资源,比如圆形底盘和小圆点。
Move.ts,将它挂载到 Joystick 节点上。

import { _decorator, Component, Node, input, Input, EventTouch, CCFloat, v3, Vec3 } from 'cc';
const { ccclass, property } = _decorator;
@ccclass('Move')
export class Move extends Component {
@property(Node)
joystickBg: Node = null; // 摇杆背景节点
@property(Node)
joystickHandle: Node = null; // 摇杆柄节点
@property({ type: CCFloat })
radius: number = 0; // 摇杆半径限制
initPosition: Vec3 = v3(); // 摇杆背景的初始位置
start() {
// 注册触摸事件监听
input.on(Input.EventType.TOUCH_MOVE, this.onTouchMove, this);
input.on(Input.EventType.TOUCH_START, this.onTouchStart, this);
input.on(Input.EventType.TOUCH_END, this.onTouchEnd, this);
input.on(Input.EventType.TOUCH_CANCEL, this.onTouchCancel, this);
// 记录摇杆背景的初始世界坐标
this.initPosition = this.joystickBg.getWorldPosition();
}
// 触摸开始,摇杆柄跟随触摸点
onTouchStart(event: EventTouch) {
console.log('onTouchStart');
const touch = event.touch;
const touchPos = v3(touch.getUILocationX(), touch.getUILocationY(), 0);
const localPos = v3();
this.joystickBg.inverseTransformPoint(localPos, touchPos);
this.joystickHandle.setPosition(localPos);
}
// 触摸移动,限制摇杆柄在半径范围内移动
onTouchMove(event: EventTouch) {
const touch = event.touch;
const touchPos = v3(touch.getUILocationX(), touch.getUILocationY(), 0);
const localPos = v3();
this.joystickBg.inverseTransformPoint(localPos, touchPos);
// 计算手指位置距离中心点的长度
const length = localPos.length();
// 方向向量,单位向量
const direction = length > 0 ? localPos.normalize() : v3(0, 0, 0);
// 限制长度最大为摇杆半径
const clampedLength = Math.min(length, this.radius);
// 计算摇杆柄最终位置
const newPos = v3(direction.x * clampedLength, direction.y * clampedLength, 0);
this.joystickHandle.setPosition(newPos);
}
// 触摸结束,摇杆柄回到中心
onTouchEnd(event: EventTouch) {
console.log('onTouchEnd');
this.joystickHandle.setPosition(Vec3.ZERO);
}
// 触摸取消,也回到中心
onTouchCancel(event: EventTouch) {
console.log('onTouchCancel');
this.joystickHandle.setPosition(Vec3.ZERO);
}
update(deltaTime: number) {
// 这里可以根据摇杆柄的位置,计算角色移动方向和速度
}
}inverseTransformPoint 将全局坐标转换为局部坐标。
radius,保证操控杆不会超出背景圆盘。
onDestroy 里解绑事件,避免内存泄漏。
update 函数里实时获取摇杆柄位置,计算方向向量和力度(摇杆柄与中心距离占半径的比例),传递给角色控制逻辑,实现移动。
touchId 管理不同触摸点。