当前位置: 首页 > news >正文

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

简介

在许多移动游戏中,虚拟操纵杆是一个重要的用户界面元素,用于控制角色或物体的移动。本文将介绍如何在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 

相关文章:

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

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

【数据分享】中国电力年鉴(2004-2022)

大家好&#xff01;今天我要向大家介绍一份重要的中国电力统计数据资源——《中国电力年鉴》。这份年鉴涵盖了从2004年到2022年中国电力统计全面数据&#xff0c;并提供限时免费下载。&#xff08;无需分享朋友圈即可获取&#xff09; 数据介绍 自1993年首次出版以来&#xf…...

两个数组的交集Ⅱ-力扣

想到的解法是使用两个map来进行记录&#xff0c;mp1用来统计num1中每个元素出现的次数。当nums2的元素能够在mp1中查找到时&#xff0c;将这个元素添加到mp2&#xff0c;按照这个规则统计得到nums2和nums1重复的元素&#xff0c;mp2中的value记录了nums2中这个元素出现的次数最…...

【TCP协议中104解析】wireshark抓取流量包工具,群殴协议解析基础

Tcp ,104 ,wireshark工具进行解析 IEC104 是用于监控和诊断工业控制网络的一种标准&#xff0c;而 Wireshark则是一款常用的网络协议分析工具&#xff0c;可以用干解析TEC104 报文。本文将介绍如何使用 Wireshark解析 IEC104报文&#xff0c;以及解析过 程中的注意事项。 一、安…...

[个人笔记] 记录docker-compose使用和Harbor的部署过程

容器技术 第三章 记录docker-compose使用和Harbor的部署过程 容器技术记录docker-compose使用和Harbor的部署过程Harborhttps方式部署&#xff1a;测试环境部署使用自签名SSL证书https方式部署&#xff1a;正式环境部署使用企业颁发的SSL证书给Docker守护进程添加Harbor的SSL证…...

详细介绍运算符重载函数,清晰明了

祝各位六一快乐~ 前言 1.为什么要进行运算符重载&#xff1f; C中预定义的运算符的操作对象只能是基本数据类型。但实际上&#xff0c;对于许多用户自定义类型&#xff08;例如类&#xff09;&#xff0c;也需要类似的运算操作。这时就必须在C中重新定义这些运算符&#xff…...

国内外知名的低代码开发平台下载地址

以下是国内外几款低代码开发平台的列表&#xff0c;包含了下载地址、适应操作系统、是否可以独立部署、优点、缺点以及是否包含流程引擎的信息。 平台名称 下载地址 适应操作系统 是否可以独立部署 优点 缺点 是否包含流程引擎 国内平台 阿里云宜搭 阿里云官网 跨平台…...

【Pr学习】01新建项目起步

【Pr学习】01新建项目起步 1、新建项目2.序列设置2.1新建序列2.2序列参数讲解2.3自定义设置 3.PR窗口认识3.1 项目窗口3.2 源窗口2.4 保存面板 4.剪辑导入4.1 素材导入4.2 视图切换4.3 时间轴4.4轨道工具4.5 节目窗口素材导入 5.基础操作5.1 取消视频音频链接5.2 单独渲染&…...

【Redis延迟队列】redis中的阻塞队列和延迟队列

阻塞队列&#xff08;RBlockingQueue&#xff09; 作用和特点&#xff1a; 实时性&#xff1a;阻塞队列用于实时处理消息。生产者将消息放入队列&#xff0c;消费者可以立即从队列中取出并处理消息。阻塞特性&#xff1a;如果队列为空&#xff0c;消费者在尝试获取消息时会被…...

el-tree常用操作

一、定义 <el-treeclass"myTreeClass":data"dirTreeData":props"dirTreeProps":filter-node-method"filterDirTree":expand-on-click-node"false"node-key"id"node-click"dirTreeNodeClick":allow-…...

SQL 语言:存储过程和触发器

文章目录 基本概述创建触发器更改和删除触发器总结 基本概述 存储过程&#xff0c;类似于高阶语言的函数或者方法&#xff0c;包含SQL语句序列&#xff0c;是可复用的语句&#xff0c;保存在数据库中&#xff0c;在服务器中执行。特点是复用&#xff0c;提高了效率&#xff0c…...

Ubuntu Linux 24.04 使用certbot生成ssl证书

设置域名 1. 将需要生成SSL证书的域名解析到IP地址 idealand.xyz <> 64.176.82.190 检查防火墙的设置 1. 首先查看防火墙的状态&#xff1a; # ufw status 2. 如果防火墙开启了&#xff0c;要开放80和443端口用于certbot验证 # ufw allow 80 # ufw allow 443 生…...

Vivado 比特流编译时间获取以及FPGA电压温度获取(实用)

Vivado 比特流编译时间获取以及FPGA电压温度获取 语言 &#xff1a;Verilg HDL 、VHDL EDA工具&#xff1a;ISE、Vivado Vivado 比特流编译时间获取以及FPGA电压温度获取一、引言二、 获取FPGA 当前程序的编译时间verilog中直接调用下面源语2. FPGA电压温度获取&#xff08;1&a…...

Window下VS2019编译WebRTC通关版

这段时间需要实现这样一个功能&#xff0c;使用WebRTC实现语音通话功能&#xff0c;第一步要做的事情就是编译WebRTC源码&#xff0c;也是很多码友会遇到的问题。 经过我很多天的踩坑终于踩出来一条通往胜利的大路&#xff0c;下面就为大家详细介绍&#xff0c;编译步骤以及踩…...

【云原生 | 60】Docker中通过docker-compose部署kafka集群

&#x1f341;博主简介&#xff1a; &#x1f3c5;云计算领域优质创作者 &#x1f3c5;2022年CSDN新星计划python赛道第一名 &#x1f3c5;2022年CSDN原力计划优质作者 &#x1f3c5;阿里云ACE认证高级工程师 &#x1f3c5;阿里云开发者社区专…...

allure测试报告用例数和 pytest执行用例数不相同问题

我出现的奇怪问题&#xff1a; pytest执行了9条用例&#xff0c;但是测试报告确只显示3条用例 我将其中的一个代码删除后&#xff0c;发现allure测试报告又正常了 我觉得很奇怪这个代码只是删除了二维数组的第一列&#xff0c;我检查了半天都找不到问题&#xff0c;只有降低版本…...

Ubuntu 离线安装 gcc、g++、make 等依赖包

前言 项目现场的服务器无法连接互联网&#xff0c;需要提前获取 gcc、g、make 等依赖包。 一、如何获取依赖包 需要准备一台可以连接互联网的电脑&#xff08;如&#xff1a;个人电脑上的虚拟机安装一个与服务器一样的系统&#xff09;&#xff0c;用于下载依赖包。之后把通过…...

Vxe UI vxe-upload 上传组件,显示进度条的方法

vxe-upload 上传组件 查看官网 https://vxeui.com 显示进度条很简单&#xff0c;需要后台支持进度就可以了&#xff0c;后台实现逻辑具体可以百度&#xff0c;这里只介绍前端逻辑。 上传附件 相关参数说明&#xff0c;具体可以看文档&#xff1a; multiple 是否允许多选 li…...

探索API接口:技术深度解析与应用实践

在当今的软件开发和数据交换领域&#xff0c;API&#xff08;应用程序编程接口&#xff09;已经成为了一个不可或缺的工具。它允许不同的软件应用程序或组件之间进行交互和通信&#xff0c;从而实现了数据的共享和功能的扩展。本文将深入探讨API接口的技术原理、设计原则以及在…...

ARM-V9 RME(Realm Management Extension)系统架构之系统安全能力的系统隔离属性

安全之安全(security)博客目录导读 目录 一、系统隔离属性 1、系统配置完整性 1.1、时间隔离 2、关键错误的报告 一、系统隔离属性 1、系统配置完整性 MSD必须确保任何可能危及其安全保证的系统寄存器的正确性和完整性。例如&#xff0c;MSD必须确认内存控制器配置是一致…...

一个班有n个学生,需要把每个学生的简单材料(姓名和学号)输入计算机保存。然后可以通过输入某一学生的姓名查找其有关资料。

当输入一个姓名后&#xff0c;程序就查找该班中有无此学生&#xff0c;如果有&#xff0c;则输出他的姓名和学号&#xff0c;如果查不到&#xff0c;则输出"本班无此人"。 为解此问题&#xff0c;可以分别编写两个函数&#xff0c;函数input_data用来输人n个…...

python的range() 函数

range() 函数 《红楼梦》&#xff0c;又名《石头记》&#xff0c;实际上是一颗神石在人间游历的故事。而这块石头&#xff0c;就是我们的主人公贾宝玉。神石在投胎成宝玉前&#xff0c;向茫茫大士和渺渺真人讲起了自己的故事&#xff1a; 女娲氏炼石补天之时&#xff0c;于大…...

ClickHouse数据管理与同步的关键技术

2024年 5 月 18 日&#xff0c;ClickHouse官方首届杭州 Meetup 活动成功举行。本次活动由 ClickHouse 和阿里云主办&#xff0c;NineData 和云数据库技术社区协办。围绕ClickHouse的核心技术、应用案例、最佳实践、数据管理、以及迁移同步等方面&#xff0c;和行业专家展开交流…...

【一竞技DOTA2】东南亚Bleed战队官宣Emo正式加盟

1、近日东南亚Bleed战队正式发布公告官宣&#xff0c;中国选手Emo以及来自蒙古选手Se加盟战队。 【公告内容如下】 我们很高兴宣布&#xff0c;战队DOTA2名单中添加了两位新成员&#xff0c;请和我们一起欢迎来自中国经验丰富的老将Emo以及来自蒙古的后起之秀Se 一号位&#…...

算法学习笔记(7.3)-贪心算法(最大切分乘问题)

目录 ##问题描述 ##问题思考 ##贪心策略确定 ##代码实现 ##时间复杂度 ##正确性验证 ##问题描述 给定一个正整数 &#x1d45b; &#xff0c;将其切分为至少两个正整数的和&#xff0c;求切分后所有整数的乘积最大是多少 ##问题思考 假设我们将 &#x1d45b; 切分为 &…...

大型企业用什么文件加密软件,五款适合企业的文件加密软件

大型企业在选择文件加密软件时&#xff0c;通常会倾向于那些能够提供全面数据保护、具有高度可定制性、易于管理且能适应复杂组织结构的解决方案。以下是一些适合大型企业使用的文件加密软件&#xff1a; 1.域智盾软件&#xff1a; 作为一款企业级文件加密软件&#xff0c;支持…...

【数据结构】二叉树运用及相关例题

文章目录 前言查第K层的节点个数判断该二叉树是否为完全二叉树例题一 - Leetcode - 226反转二叉树例题一 - Leetcode - 110平衡二叉树 前言 在笔者的前几篇篇博客中介绍了二叉树的基本概念及基本实现方法&#xff0c;有兴趣的朋友自己移步看看。 这篇文章主要介绍一下二叉树的…...

Java基础知识点(反射、注解、JDBC、TCP/UDP/URL)

文章目录 反射反射的定义class对象反射的操作 注解注解的定义注解的应用注解的分类基准注解元注解 自定义注解自定义规则自定义demo JDBCTCP/UDP/URLTCPUDPURL 反射 反射的定义 Java Reflection是Java被视为动态语言的基础啊&#xff0c; 反射机制允许程序在执行期间接入Refl…...

postgressql——Tuple学习(2)

Tuple含义 作用 PG并没有像Oracle那样的undo来存放旧数据&#xff0c;而且PG没有真正意义上的delete&#xff0c;而是将旧版本直接存放于relation文件中&#xff0c;也就是成为了dead tuple。我们可以理解成“过期的数据”含义 tuple就相当于一个存储数据的小容器&#xff0c;…...

Linux日志管理

文章目录 一、日志管理概述1.1、日志管理介绍1.2、日志管理的重要性1.3、日志管理的组件1.4、日志管理的流程1.5、日志管理的挑战 二、日志分类介绍2.1、windows日志类别2.1.1、Application Log2.1.2、Security Log2.1.3、System Log2.1.4、Setup Log2.1.5、ForwardedEvents Lo…...