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

cocos creator 3.x 手搓背包拖拽装备

 项目背景:

游戏背包 需要手动 拖拽游戏装备到 装备卡槽中,看了下网上资料很少。手搓了一个下午搞定,现在来记录下实现步骤;

功能拆分:

一个完整需求,我们一般会把它拆分成 几个小步骤分别造零件。等都造好了我们就能 装配到一起 形成一个完成功能。以下是对上面功能的 步骤拆分:

  1. 背包详情的展示,点击背包中的物品 展示一个详情页面(因为 是在 ScrollView 中拖拽 ScrollView 的元素 会造成 ScrollView 滚动)所有我们直接拖拽 详情页面中的元素就能 避免对 ScrollView 的影响。(如果没有详情可以 先生成一个一样的元素放置的 ScrollView 外层)
  2. 实现 拖拽元素,本身是对 拖拽事件的监听 来完成对元素位置的设置。这里有个知识点 触点坐标 到 世界坐标的转换
  3. 能拖拽元素了 那么我们就需要把 元素放在对应的位置, 实际上就是在拖拽的时候 判断两个元素的位置,根据需求我们这里是直接判断的 元素的 x坐标;来判断拖拽元素 是否到了 对应的卡槽;
  4. 既然能判断到那个具体卡槽了,我们停止拖拽,那就装备到对应的卡槽,要是没有到卡槽位置,我们隐藏拖拽元素 返回 (假装什么也没发生)

1.背包装备详情

点击装备展示,对应详情信息,应为装备位置不固定,

  1. 展示的时候就需要 通过 背包元素的 位置 来计算详情页面展示的位置
  2. 并且如果是 在边缘位置还要修改要展示的位置,然后修正位置信息后 在做展示

这里有一个技术点就是 坐标位置的转换

想要对比两个节点元素 或者 参照当前节点 设置另一个节点位置信息(不在同一个父节点的时候) 需要把他们转换在 同一个坐标系及(参照同一个父节点)

 

问题: 由于图中的 粉色ScrollView item  和 详情不是在用一个坐标参照中, 如果我们直接获取 item 位置 赋值给 详情元素 那肯定无法让他们两位置一直;

 

解决问题思路:

  先计 算出 item 世界坐标,然后再把这个坐标转化到 详情页面的局部坐标他们世界坐标一直,局部坐标不一致

同为 cocos creator 坐标转换需要使用 使用节点父元素计算:

https://docs.cocos.com/creator/3.8/api/zh/class/UITransform?id=convertToWorldSpaceARicon-default.png?t=N7T8http://convertToWorldSpaceAR

ItemworldPositon = item.parent.getComponent(UITransform).convertToWorldSpaceAR(item.getPosition());详情面板位置 =  详情面板.parent.getComponent(UITransform).convertToNodeSpaceAR(                  ItemworldPositon)
  • convertToNodeSpaceAR
    /*** @en* Converts a Point to node (local) space coordinates.** @zh* 将一个 UI 节点世界坐标系下点转换到另一个 UI 节点 (局部) 空间坐标系,这个坐标系以锚点为原点。* 非 UI 节点转换到 UI 节点(局部) 空间坐标系,请走 Camera 的 `convertToUINode`。** @param worldPoint @en Point in world space.*                   @zh 世界坐标点。* @param out @en Point in local space.*            @zh 转换后坐标。* @returns @en Return the relative position to the target node.*          @zh 返回与目标节点的相对位置。* @example* ```ts* const newVec3 = uiTransform.convertToNodeSpaceAR(cc.v3(100, 100, 0));* ```*/
    convertToNodeSpaceAR(worldPoint: math.Vec3, out?: math.Vec3): math.Vec3;
  • convertToWorldSpaceAR
    /*** @en* Converts a Point in node coordinates to world space coordinates.** @zh* 将距当前节点坐标系下的一个点转换到世界坐标系。** @param nodePoint @en Point in local space.*                  @zh 节点坐标。* @param out @en Point in world space.*            @zh 转换后坐标。* @returns @en Returns the coordinates in the UI world coordinate system.*          @zh 返回 UI 世界坐标系。* @example* ```ts* const newVec3 = uiTransform.convertToWorldSpaceAR(3(100, 100, 0));* ```*/
    convertToWorldSpaceAR(nodePoint: math.Vec3, out?: math.Vec3): math.Vec3;
 /*** 坐标计算* @param target ScrollView 中被点击的 item 元素 * @param item  数据*/
public setData(target: Node, item: CoachCharacterItem) {//console.log('target.getPosition():', target.getPosition());//当前节点本地坐标转世界坐标、//世界坐标转到 对应的 节点坐标let vec: Vec3 = this.rootParemt.getComponent(UITransform).convertToNodeSpaceAR(target.parent.getComponent(UITransform).convertToWorldSpaceAR(target.getPosition()));console.log(vec)//修正位置if (vec.x < 400) {vec.x += 250;} else {vec.x -= 250;}if (vec.y > 140) {vec.y = 140;} else if (vec.y < -100) {vec.y = -100;}this.node.setPosition(vec);this.node.active = true;
}

2.拖拽元素

我们给详情页面添加 拖拽事件的监听:

这里有个技术点 tuochMove 中获取到的坐标实际上是 触点坐标, 我们需要将这个坐标 转化到 UI坐标才能对 UI元素赋值

//添加监听事件
onLoad() {this.node.on(Node.EventType.TOUCH_START, this.touchStart, this);this.node.on(Node.EventType.TOUCH_MOVE, this.touchMove, this);this.node.on(Node.EventType.TOUCH_END, this.touchEnd, this)this.node.on(Node.EventType.TOUCH_CANCEL, this.touchCancel, this)
}//展示只有 在拖拽情况下才显示的 元素 equipmentFly
touchStart(event: EventTouch) {//Log.trace('touchStart');//展示 拖拽 元素 equipmentFlythis.equipmentFly.node.active = true;
}//获取 触点坐标位置
touchMove(event: EventTouch) {//更新 拖拽元素位置this.equipmentFly.updatePosition(event.getLocation());
}//结束拖拽 隐藏拖拽元素
touchCancel(event: EventTouch) {//console.log('touchCancel');//隐藏 拖拽 元素 equipmentFlythis.equipmentFly.node.active = false;//执行 拖拽完毕的判断逻辑this.equipmentFly.onConfirm();//重置拖拽元素的位置this.equipmentFly.resetPostion(new Vec3(0, 50));}
//结束拖拽
touchEnd(event: EventTouch) {//console.log('touchEnd');//隐藏 拖拽 元素 equipmentFlythis.equipmentFly.node.active = false;//执行 拖拽完毕的判断逻辑this.equipmentFly.onConfirm();//重置拖拽元素的位置this.equipmentFly.resetPostion(new Vec3(0, 50));
}
//隐藏详情面板
public hideNoticePanel() {this.equipmentFly.node.active = false;this.equipmentFly.resetPostion(new Vec3(0, 50));this.node.active = false;
}
触点坐标转换UI坐标的实现:

触点坐标转 UI 坐标需要通过  camera.screenToWorld(触点坐标)

Cocos Creator APIDescriptionicon-default.png?t=N7T8https://docs.cocos.com/creator/3.8/api/zh/class/renderer.scene.Camera?id=screenToWorld大概逻辑整理如下:

  1. 拿到 拖拽 事件传递的 触点坐标
  2. 触点坐标 通过 camera 转 世界坐标
  3. 世界坐标转 UI局部坐标赋值 拖拽元素坐标    这样就能实现 拖拽元素随着手指滑动而移动

//拿到摄像机
onLoad() {//获取摄像机this.camera = find('Canvas/Camera').getComponent(Camera);//获取卡槽1 的 世界坐标this.vec3WorldBattle = this.nodeWearBattle.parent.getComponent(UITransform).convertToWorldSpaceAR(this.nodeWearBattle.getPosition());//获取卡槽1 的 世界坐标this.vec3WorldReward = this.nodeWearReward.parent.getComponent(UITransform).convertToWorldSpaceAR(this.nodeWearReward.getPosition());}/*** 触点坐标转换 * 最后使用UI坐标赋值* @param vec */
updatePosition(vec: Vec2) {this.vec3Pos.x = vec.x;this.vec3Pos.y = vec.y;//触点坐标转 世界坐标this.vec3WorldNode = this.camera.screenToWorld(this.vec3Pos);// 世界坐标转 UI局部坐标this.vec3new = this.node.parent.getComponent(UITransform).convertToNodeSpaceAR(this.vec3WorldNode);this.node.position = this.vec3new;//计算 拖拽元素 和 两个卡槽的 x轴距离 这里  distance 为 50个单位if (Math.abs(this.vec3WorldNode.x - this.vec3WorldBattle.x) < this.distance) {//距离到了 通知界面展示 卡槽1 选中框this.coachCharacterEquipmentView.onPreview(this.equipment, 0);} else if (Math.abs(this.vec3WorldNode.x - this.vec3WorldReward.x) < this.distance) {       //距离到了 通知界面展示 卡槽2 选中框this.coachCharacterEquipmentView.onPreview(this.equipment, 1);} else {//这里处理 距离都没到的逻辑 移除选中框 以及 从 已经选中状态到 没选中状态的切换this.coachCharacterEquipmentView.onPreview(null, -1);}}

3.卡槽判定

通过上面的代码我们已经可以实现,拖转元素到 卡槽函数的调用:

//计算 拖拽元素 和 两个卡槽的 x轴距离 这里  distance 为 50个单位
if (Math.abs(this.vec3WorldNode.x - this.vec3WorldBattle.x) < this.distance) {//距离到了 通知界面展示 卡槽1 选中框this.coachCharacterEquipmentView.onPreview(this.equipment, 0);
} else if (Math.abs(this.vec3WorldNode.x - this.vec3WorldReward.x) < this.distance) {//距离到了 通知界面展示 卡槽2 选中框this.coachCharacterEquipmentView.onPreview(this.equipment, 1);
} else {//这里处理 距离都没到的逻辑 移除选中框 以及 从 已经选中状态到 没选中状态的切换this.coachCharacterEquipmentView.onPreview(null, -1);
}
因为我们一个卡槽有多个 装备位置,需要响应的装备展示 对应的卡槽;
this.coachCharacterEquipmentView.onPreview(data,soltIndex);

函数onPreview 当到对应的卡槽就把数据传递过去,具体不够就传 null,过去

卡槽现实的我们就略过去;

 

卡槽数据的确认:

这个环节就对应的是 到对应的卡槽,并且松手:

上面的代码中我们已经加过监听了;通过实践发现 即便我同时监听了 TOUCH_END  和 TOUCH_CANCEL 他也只有一个会执行;所有我两个都加了

所以一来逻辑就清晰了:

  1. 当拖拽元素到卡槽中的时候,我们已经传递参数过去了,并且 我们当拖出 卡槽的时候还把数据 赋值为  null,
  2. 当我们停止拖拽的时候 判断下 传递过去的 数据是否为 null,
  3. 如果为 null  则说明 没有在卡槽中停止 拖拽,不为空则为 在卡槽中停止的拖拽
touchCancel(event: EventTouch) {//console.log('touchCancel');this.equipmentFly.node.active = false;this.equipmentFly.onConfirm();this.equipmentFly.resetPostion(new Vec3(0, 50));}
touchEnd(event: EventTouch) {//console.log('touchEnd');this.equipmentFly.node.active = false;this.equipmentFly.onConfirm();this.equipmentFly.resetPostion(new Vec3(0, 50));
}

到这里基本上级功能都实现了。而且我们的 距离判断逻辑只有在 拖拽时候才会执行,应该说性能还不错!

相关文章:

cocos creator 3.x 手搓背包拖拽装备

项目背景&#xff1a; 游戏背包 需要手动 拖拽游戏装备到 装备卡槽中&#xff0c;看了下网上资料很少。手搓了一个下午搞定&#xff0c;现在来记录下实现步骤&#xff1b; 功能拆分&#xff1a; 一个完整需求&#xff0c;我们一般会把它拆分成 几个小步骤分别造零件。等都造好了…...

运维开发.Kubernetes探针与应用

运维系列 Kubernetes探针与应用 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this article:https://blog.csdn.net/qq_28550263…...

Spring 框架:Java 企业级开发的基石

文章目录 序言Spring 框架的核心概念Spring 框架的主要模块Spring Boot&#xff1a;简化 Spring 开发Spring Cloud&#xff1a;构建微服务架构实际案例分析结论 序言 Spring 框架自 2002 年发布以来&#xff0c;已经成为 Java 企业级开发的标准之一。它通过提供全面的基础设施…...

在Docker中使用GPU

一、安装nvidia-container-toolkit 总之一句话&#xff1a;nvidia-docker和nvidia-docker2&#xff0c;nvidia-container-runtime 已经被英伟达迭代了&#xff0c;可以认为nvidia-container-toolkit是nvidia-docker和nvidia-docker2&#xff0c; nvidia-container-runtime 的替…...

vue3 前端实现导出下载pdf文件

这样的数据实现导出 yourArrayBufferOrByteArray 就是后端返回数据 // 创建Blob对象const blob new Blob([new Uint8Array(res)], { type: application/pdf })// 创建一个表示该Blob的URLconst url URL.createObjectURL(blob);// 创建一个a标签用于下载const a document.cr…...

AI智能体研发之路-模型篇(五):pytorch vs tensorflow框架DNN网络结构源码级对比

博客导读&#xff1a; 《AI—工程篇》 AI智能体研发之路-工程篇&#xff08;一&#xff09;&#xff1a;Docker助力AI智能体开发提效 AI智能体研发之路-工程篇&#xff08;二&#xff09;&#xff1a;Dify智能体开发平台一键部署 AI智能体研发之路-工程篇&#xff08;三&am…...

电商物流查询解决方案助力提升消费者体验

截至2023年12月&#xff0c;中国网络购物用户规模达9.15亿人&#xff0c;占网民整体的83.8%。这一庞大的数字不仅展现了电子商务的蓬勃发展&#xff0c;也标志着数字零售企业营销战略的转变——从以产品和流量为核心&#xff0c;到用户为王的新阶段。因此&#xff0c;提升消费者…...

【深度密码】神经网络算法在机器学习中的前沿探索

目录 &#x1f69d;前言 &#x1f68d;什么是机器学习 1. 基本概念 2. 类型 3. 关键算法 4. 应用领域 5. 工作流程 &#x1f68b;什么是神经网络 基本结构 &#x1f682;神经网络的工作原理 前向传播&#xff08;Forward Propagation&#xff09;&#xff1a; 损失函…...

搭载算能 BM1684 芯片,面向AI推理计算加速卡

搭载算能 BM1684 芯片&#xff0c;是面向AI推理的算力卡。可集成于服务器、工控机中&#xff0c;高效适配市场上所有AI算法&#xff0c;实现视频结构化、人脸识别、行为分析、状态监测等应用&#xff0c;为智慧城市、智慧交通、智慧能源、智慧金融、智慧电信、智慧工业等领域进…...

Python开发 我的世界 Painting-the-World: Minecraft 像素图片生成器

简介 Painting-the-World 是一款创新的工具&#xff0c;专为《我的世界》(Minecraft) 玩家及创作者设计&#xff0c;旨在将数字图片转变为游戏内的像素艺术。通过利用 RCON (Remote Console) 协议&#xff0c;本项目可以直接与《我的世界》服务器对话&#xff0c;根据输入的图…...

【经验分享】盘点“食用“的写文素材

一、构建框架 简介 1. 身份 擅长领域 2. 博客内容 3. 目前示例&#xff1a; 阿里云专家博主&#xff0c;华为云-云享专家&#xff0c;专注前、后端开发 博客内容&#xff1a;前后端实战教学、源码剖析、常见面试知识解析、算法题解与心得、日常考研总结等 目前正在备战考研&…...

实习碰到的问题w1

1.vueelementUI在输入框中按回车键会刷新页面 当一个 form 元素中只有一个输入框时&#xff0c;在该输入框中按下回车应提交该表单。如果希望阻止这一默认 行为&#xff0c;可以在 <el-form> 标签上添加 submit.native.prevent 。 参考&#xff1a;element-ui 表单 form …...

c#实现BPM系统网络传输接口,http协议,post

BPM通过http协议实现网络传输&#xff0c;语言使用.net(c#)&#xff0c;在这里只提供一个接口&#xff0c;具体代码如下,请参照&#xff1a; public string MakeRequest(string parameters) { ServicePointManager.ServerCertificateValidationCallback new Syst…...

如何修改开源项目中发现的bug?

如何修改开源项目中发现的bug&#xff1f; 目录 如何修改开源项目中发现的bug&#xff1f;第一步&#xff1a;找到开源项目并建立分支第二步&#xff1a;克隆分支到本地仓库第三步&#xff1a;在本地对项目进行修改第四步&#xff1a;依次使用命令行进行操作注意&#xff1a;Gi…...

结构设计模式 - 代理设计模式 - JAVA

代理设计模式 一. 介绍二. 代码示例2.1 定义 CommandExecutor 类2.2 定义 CommandExecutorProxy代理类2.3 模拟客户端2.4 测试结果 三. 结论 前言 这是我在这个网站整理的笔记,有错误的地方请指出&#xff0c;关注我&#xff0c;接下来还会持续更新。 作者&#xff1a;神的孩子…...

企业了解这些cad图纸加密方法,再也不怕图纸被盗了!

在竞争激烈的商业环境中&#xff0c;企业的核心技术、设计图纸和创意是维持其市场地位和竞争优势的关键。CAD图纸作为产品设计的重要载体&#xff0c;其安全性自然成为企业关注的焦点。为了确保CAD图纸不被非法获取或盗用&#xff0c;企业需要采取一系列有效的加密方法。本文将…...

# 详解 JS 中的事件循环、宏/微任务、Primise对象、定时器函数,以及其在工作中的应用和注意事项

为什么会突然想到写这么一个大杂烩的博文呢&#xff0c;必须要从笔者几年前的一次面试说起 当时的我年轻气盛&#xff0c;在简历上放了自己的博客地址&#xff0c;而面试官应该是翻了我的博客&#xff0c;好几道面试题都是围绕着我的博文来提问 其中一个问题&#xff0c;直接…...

神经网络与深度学习——第14章 深度强化学习

本文讨论的内容参考自《神经网络与深度学习》https://nndl.github.io/ 第14章 深度强化学习 深度强化学习 强化学习&#xff08;Reinforcement Learning&#xff0c;RL&#xff09;&#xff0c;也叫增强学习&#xff0c;是指一类从与环境交互中不断学习的问题以及解决这类问题…...

centOS 编译C/C++

安装C和C编译器 yum -y install gcc*查看CenterOS系统信息 cat /etc/system-releaseCentOS Linux release 8.2.2004 (Core)查看gcc版本 gcc --versiongcc (GCC) 8.5.0 20210514 (Red Hat 8.5.0-4) Copyright (C) 2018 Free Software Foundation, Inc. This is free software…...

java——网络原理初识

T04BF &#x1f44b;专栏: 算法|JAVA|MySQL|C语言 &#x1faf5; 小比特 大梦想 目录 1.网络通信概念初识1.1 IP地址1.2端口号1.3协议1.3.1协议分层协议分层带来的好处主要有两个方面 1.3.2 TCP/IP五层 (或四层模型)1.3.3 协议的层和层之间是怎么配合工作的 1.网络通信概念初识…...

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...

AtCoder 第409​场初级竞赛 A~E题解

A Conflict 【题目链接】 原题链接&#xff1a;A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串&#xff0c;只有在同时为 o 时输出 Yes 并结束程序&#xff0c;否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...

python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)

更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...

让AI看见世界:MCP协议与服务器的工作原理

让AI看见世界&#xff1a;MCP协议与服务器的工作原理 MCP&#xff08;Model Context Protocol&#xff09;是一种创新的通信协议&#xff0c;旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天&#xff0c;MCP正成为连接AI与现实世界的重要桥梁。…...

selenium学习实战【Python爬虫】

selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...

Ubuntu Cursor升级成v1.0

0. 当前版本低 使用当前 Cursor v0.50时 GitHub Copilot Chat 打不开&#xff0c;快捷键也不好用&#xff0c;当看到 Cursor 升级后&#xff0c;还是蛮高兴的 1. 下载 Cursor 下载地址&#xff1a;https://www.cursor.com/cn/downloads 点击下载 Linux (x64) &#xff0c;…...

「全栈技术解析」推客小程序系统开发:从架构设计到裂变增长的完整解决方案

在移动互联网营销竞争白热化的当下&#xff0c;推客小程序系统凭借其裂变传播、精准营销等特性&#xff0c;成为企业抢占市场的利器。本文将深度解析推客小程序系统开发的核心技术与实现路径&#xff0c;助力开发者打造具有市场竞争力的营销工具。​ 一、系统核心功能架构&…...

WEB3全栈开发——面试专业技能点P7前端与链上集成

一、Next.js技术栈 ✅ 概念介绍 Next.js 是一个基于 React 的 服务端渲染&#xff08;SSR&#xff09;与静态网站生成&#xff08;SSG&#xff09; 框架&#xff0c;由 Vercel 开发。它简化了构建生产级 React 应用的过程&#xff0c;并内置了很多特性&#xff1a; ✅ 文件系…...

车载诊断架构 --- ZEVonUDS(J1979-3)简介第一篇

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 做到欲望极简,了解自己的真实欲望,不受外在潮流的影响,不盲从,不跟风。把自己的精力全部用在自己。一是去掉多余,凡事找规律,基础是诚信;二是…...

《Offer来了:Java面试核心知识点精讲》大纲

文章目录 一、《Offer来了:Java面试核心知识点精讲》的典型大纲框架Java基础并发编程JVM原理数据库与缓存分布式架构系统设计二、《Offer来了:Java面试核心知识点精讲(原理篇)》技术文章大纲核心主题:Java基础原理与面试高频考点Java虚拟机(JVM)原理Java并发编程原理Jav…...