首页 > 其他分享 >cocos creator 3.x实现手机虚拟操作杆

cocos creator 3.x实现手机虚拟操作杆

时间:2024-06-01 18:10:40浏览次数:26  
标签:node cocos creator 触摸 操纵杆 位置 虚拟 let 节点

简介

在许多移动游戏中,虚拟操纵杆是一个重要的用户界面元素,用于控制角色或物体的移动。本文将介绍如何在Unity中实现虚拟操纵杆,提供了一段用于移动控制的代码。我们将讨论不同类型的虚拟操纵杆,如固定和跟随,以及如何在实际游戏中使用这些操纵杆。

unity2022版本实现虚拟操作杆可以查看这篇文章 点击查看

界面节点设置


1. 添加一个Canvas节点

首先,我们需要创建一个画布节点,这是我们整个界面的基础。这个节点将允许我们绘制和排列其他元素。

2. 在Canvas节点下添加一个Camera节点

接下来,我们将在Canvas节点下创建一个Camera节点。这个Camera节点是查看操作按钮的摄像头

2. 在Canvas节点下添加一个Joystick节点

这个Joystick节点将充当容器,用于组织和管理我们的界面元素。

3. 在Joystick节点下添加两个Sprite节点

在Joystick节点中,我们将添加两个Sprite节点。这两个Image节点具有不同的用途:

a. 背景节点:第一个Sprite节点将用作背景,为整个界面提供背景图像或颜色。

b. 操作按钮节点:第二个Sprite节点将用于显示操作按钮或其他交互元素。

Canvas (画布)
│
└─ Camera (摄像机)
└─ Joystick (虚拟操作父节点)
   │
   ├─ Bg(背景)
   │
   └─ Btn(操作按钮)

截图可以这样:

 

脚本编写


简要说明:


因为编写的是虚拟操作杆 需要添加三个事件:

触摸开始(touchStart),拖动(touchMove),触摸结束(touchEnd)

在触摸开始记录拖动的一些起始坐标。

在拖动中移动操作按钮节点如果是操作角色移动这里就可以操作移动角色

在触摸结束的时候重置坐标

        1.touchStart方法:描述touchStart方法,它处理当玩家触摸操纵杆时的行为。根据操纵杆类型(固定或跟随),它设置操纵杆的初始位置。

        2.touchMove方法:详细解释touchMove方法,这是当玩家拖动操纵杆时执行的代码。说明如何计算操纵杆输入的方向,以及如何限制操纵杆的移动范围。

        3.touchEnd方法:描述touchEnd方法,用于当玩家释放操纵杆时重置相关变量和位置,同时停止玩家的移动。在初始化引用的时候可以传入参数(JoystickType)控制虚拟操作杆是固定的还是跟随触摸点的

 

完整的脚本如下:

import { Component, assetManager, _decorator, Node, Prefab, instantiate, JsonAsset, UITransform, Vec3, Widget, Graphics, Enum, input, Input, EventTouch, RichText, Label, sys, CCString, Vec2, Camera } from "cc"
import utils from "../../../utils";
const { ccclass, property, type } = _decorator;

// 定义操纵杆的类型
export enum JoystickType {
    FIXED,    // 固定类型的操纵杆
    FOLLOW    // 跟随类型的操纵杆
}

// 定义操纵杆的显示类型
export enum JoystickShowType {
    ALWAYS_DISPLAY,         // 一直显示
    NOT_ALWAYS_DISPLAY      // 仅在操作时显示
}

@ccclass('Joystick')
export default class Joystick extends Component {
    // 绑定Camera组件,用于获取屏幕触摸位置
    @property(Camera)
    public camera: Camera;

    // 绑定操纵杆节点
    @property(Node)
    public joystick: Node;

    // 绑定操纵杆背景节点
    @property(Node)
    public joystickBG: Node;

    // 绑定操纵杆的父节点
    @property(Node)
    public joystickParent: Node;

    // 存储操纵杆的移动向量
    public joystickVec: Vec3;

    // 指定操纵杆的类型(固定或跟随)
    @property({
        type: Enum(JoystickType),
        tooltip: "类型"
    })
    public joystickType: JoystickType = JoystickType.FIXED;

    // 指定操纵杆的显示类型(一直显示或仅操作时显示)
    @property({
        type: Enum(JoystickShowType),
        tooltip: "显示类型"
    })
    public joystickShowType: JoystickShowType = JoystickShowType.ALWAYS_DISPLAY;

    // 触摸开始时操纵杆的位置
    private joystickTouchPos: Vec3;

    // 操纵杆背景的原始位置
    private joystickOriginalPos: Vec3;

    // 操纵杆背景的半径
    private joystickRadius: number;

    // 标识是否开始拖动操纵杆
    public startDrop: boolean;

    // 初始化
    start() {
        // 根据操纵杆显示类型设置其初始显示状态
        if (this.joystickShowType === JoystickShowType.NOT_ALWAYS_DISPLAY) {
            this.joystickParent.active = false;
        } else {
            this.joystickParent.active = true;
        }

        // 保存操纵杆背景的原始位置
        this.joystickOriginalPos = this.joystickBG.position.clone();

        // 计算操纵杆背景的半径(背景节点宽度的一半)
        this.joystickRadius = utils.getNodeSize(this.joystickBG).width / 2;

        // 绑定触摸事件的处理函数
        this.node.on(Input.EventType.TOUCH_END, this.touchEnd, this);
        this.node.on(Input.EventType.TOUCH_START, this.touchStart, this);
        this.node.on(Input.EventType.TOUCH_MOVE, this.touchMove, this);
    }

    // 在组件销毁时,解除触摸事件的绑定
    protected onDestroy(): void {
        this.node.off(Input.EventType.TOUCH_END, this.touchEnd, this);
        this.node.off(Input.EventType.TOUCH_START, this.touchStart, this);
        this.node.off(Input.EventType.TOUCH_MOVE, this.touchMove, this);
    }

    /**
     * 获取触摸事件在节点坐标系中的位置
     *
     * @param e 触摸事件对象
     * @returns 触摸事件在节点坐标系中的位置
     */
    getEventPosInNodePos(e: EventTouch) {
        // 获取触摸点的屏幕坐标
        let p = e.getLocation();

        // 将屏幕坐标转换为世界坐标
        let word = this.camera.screenToWorld(utils.getVec3(p));

        // 获取UITransform组件,将世界坐标转换为节点本地坐标
        let uiTransform = this.node.getComponent(UITransform);
        let localPos = uiTransform.convertToNodeSpaceAR(new Vec3(word.x, word.y));

        return localPos;
    }

    // 触摸开始事件处理函数
    touchStart(e: EventTouch) {
        this.startDrop = true;
        this.joystickParent.active = true;

        // 根据操纵杆类型设置初始触摸位置
        if (this.joystickType == JoystickType.FIXED) {
            // 固定类型的操纵杆,设置触摸位置为操纵杆背景的原始位置
            this.joystickTouchPos = this.joystickOriginalPos.clone();
        } else if (this.joystickType == JoystickType.FOLLOW) {
            // 跟随类型的操纵杆,将操纵杆和背景设置为触摸位置
            this.joystick.setPosition(utils.nodePosToNodePos(this.getEventPosInNodePos(e), this.node, this.joystick.parent));
            this.joystickBG.setPosition(this.joystick.position);
            this.joystickTouchPos = this.joystick.position.clone();
        }

        // 处理触摸移动
        this.touchMove(e);
    }

    /**
     * 触摸移动事件处理函数
     *
     * @param e 触摸事件对象
     */
    touchMove(e: EventTouch) {
        // 如果没有开始拖动,则不处理
        if (this.startDrop === false) {
            return;
        }

        // 获取操纵杆触摸位置的副本
        let joystickTouchPos = this.joystickTouchPos.clone();

        // 获取触摸事件在节点坐标系中的位置
        let dragPos = this.getEventPosInNodePos(e);

        // 获取操纵杆背景相对于节点的本地坐标
        let nodePos = utils.nodePosToNodePos(joystickTouchPos, this.joystickBG.parent, this.node);

        // 计算操纵杆的移动向量,并归一化
        let joystickVec = dragPos.clone().subtract(nodePos).normalize();

        // 计算触摸点与操纵杆触摸位置之间的距离
        let joystickDist = Vec3.distance(dragPos, nodePos);

        // 限制操纵杆在指定半径范围内移动
        if (joystickDist < this.joystickRadius) {
            // 如果距离小于半径,直接设置操纵杆的位置
            let pos = joystickTouchPos.add(joystickVec.multiplyScalar(joystickDist));
            this.joystick.setPosition(pos);
        } else {
            // 如果距离大于半径,设置操纵杆到半径位置
            let pos = joystickTouchPos.add(joystickVec.multiplyScalar(this.joystickRadius));
            this.joystick.setPosition(pos);
        }
    }

    /**
     * 触摸结束事件处理函数
     *
     * @param e 触摸事件对象
     */
    touchEnd(e: EventTouch) {
        // 标识结束拖动
        this.startDrop = false;

        // 根据操纵杆显示类型设置其显示状态
        if (this.joystickShowType === JoystickShowType.NOT_ALWAYS_DISPLAY) {
            this.joystickParent.active = false;
        } else {
            this.joystickParent.active = true;
        }

        // 将操纵杆移动向量重置为零
        this.joystickVec = Vec3.ZERO;

        // 将操纵杆和背景位置重置为原始位置
        this.joystick.setPosition(this.joystickOriginalPos);
        this.joystickBG.setPosition(this.joystickOriginalPos);
    }
}

大致效果如下:

固定

跟随

社交:

QQ群:859055710 

标签:node,cocos,creator,触摸,操纵杆,位置,虚拟,let,节点
From: https://www.cnblogs.com/huihuishijie/p/18226239

相关文章

  • VMware虚拟机中Centos最小化安装后的常用配置
    每次在虚拟机安装linux之后都要配置固定ip,安装docker等操作,所以使用此文章,记录以后快速配置1.设置静态IP设置静态ip前,如果没有配置过虚拟机网络的,先进行如下配置:关于VMwareWorkstationPro中虚拟机无法连接外网问题解决在虚拟机界面,配置静态IP,方便使用shell工具进行......
  • ESXI虚拟机新增现有硬盘问题
    Esxi6.7安装openwrt,固件img通过StarWindConverter转换成Esxi硬盘格式后,直接在虚拟机新增硬盘。再次编辑此虚拟机即提示“请输入大于原始容量的磁盘大小”,此时随意更改会导致硬盘镜像内容损坏。不更改又不能保存其他项目更改内容。所以需要特定操作变更现有硬盘大小。SSH登录到E......
  • 在Linux中,如何进行虚拟化技术的应用?
    在Linux中应用虚拟化技术,主要涉及搭建和管理虚拟化环境,以实现资源的高效利用和灵活部署。以下是在Linux上使用KVM(Kernel-basedVirtualMachine)这一常见虚拟化技术的应用步骤:1.检查硬件虚拟化支持确保你的CPU支持硬件虚拟化(如Intel的VT-x或AMD的AMD-V)。使用以下命令检查:egre......
  • 76文章解读与程序——电网技术EI\CSCD\北大核心《基于阶梯碳交易的含P2G-CCS耦合和
    76号资源-复现源程序:论文可在知网下载《基于阶梯碳交易的含P2G-CCS耦合和燃气掺氢的虚拟电厂优化调度》本人博客有解读资源-CSDN文库https://download.csdn.net/download/LIANG674027206/89139682https://download.csdn.net/download/LIANG674027206/89139682......
  • 基于LabVIEW虚拟示波器设计
    随着计算机技术的发展,传统仪器开始向计算机化的方向发展。虚拟仪器是90年代提出的新概念。虚拟仪器技术的提出与发展,标志着二十一世纪自动测试与电子测量仪器领域技术发展的一个重要方向。所谓虚拟仪器,就是在通用的计算机平台上定义和设计仪器的测试功能,使用者操作这台计算机,就......
  • Ubuntu上使用QT creator运行cuda程序
    突发奇想想尝试一下QT界面中使用CUDA加速过的程序,然后查了一下资料,总结一下有以下几点吧1、CUDA配置全部放在.pro文件中2、main.cpp为主函数使用g++编译3、kernel.cu为核函数使用nvcc编译不多说上代码以下为main.cpp代码   #include<QtCore/QCoreApplication>       ......
  • AWC6.3.8 开发环境搭建(虚拟机中)
    前提安装完毕awc,并且能够正常访问在配置nodejs环境变量添加NODE_PATH下载vscode并安装(也可以用其他工具)拷贝stageC:\Siemens\Teamcenter14\aws2\stage=>C:\dev\stage修改initenv.cmd,增加两行运行在开发工具中cdc:/dev/stage#执行initenv.cmd.\init......
  • windows下用vmware安装的mac虚拟机更改分辨率踩坑日记
    折腾了很久,终于把mac虚拟机安装上了!首先用unlocker解锁vmware安装macos!然后从网上下载苹果系统的安装包!注意,不要dmg镜像,要cdr格式的!装好后觉得分辨率太小!想更改分辨率!于是百度!网上说的修改com.apple.Boot.plist文件根本行不通啊!苹果限制了你修改这个文件,因为新版本的系统没有......
  • KVM创建虚拟机
    第一章初始化虚拟机virt-install-ntest-kubernetes-node04-8.77--vcpus16-r61440--disk/data/kvm/image/test-kubernetes-node04-sys.qcow2,size=50--disk/data/kvm/image/test-kubernetes-node04-data.qcow2,size=1024--location/data/kvm/iso/CentOS-7-x86_64-M......
  • 同样都是网络虚拟化技术,QinQ和VXLAN有啥区别?
    你好,这里是网络技术联盟站,我是瑞哥。公众号后台,有小伙伴想要了解一下QinQ和VXLAN,今天安排一下。QinQQinQ,也称为双重VLAN标记,是一种用于扩展VLAN数量和提供多租户隔离的技术。它允许在标准的802.1Q标签之外,再增加一个802.1Q标签,从而形成“外层标签”和“内层标签”的双重......