在Cocos2d中拖动组件并吸附到节点
最近在学习制作小游戏,要实现一个拖动吸附效果,这里简单实现一下

代码实现
定义节点和函数功能
在properties里新建一个对象,用来接收目标区域的节点
properties:{
sense: {
defaule: null,
type: cc.Node,
}
}
然后在小车节点里绑定这个脚本,将要测试的目标节点拖动到属性检查器的sense
这里用小车来表示要移动的组件,先在onload()内定义小车组件,设置位置,以及定义三个触摸事件函数
onload() {
this.carPos = cc.v2(0, 0);
// 定义一个触摸移动控件
this.node.setPosition(this.carPos.x, this.carPos.y);
this.origin = this.node.convertToWorldSpace(cc.v2(0, 0));
// 获取小车移动前的坐标
// 对当前节点设置位置
this.node.on("touchstart", this.touchStart, this);
this.node.on("touchmove", this.touchMove, this);
this.node.on("touchend", this.touchEnd, this);
// 定义三个触摸事件函数
}
然后就是对三个触摸事件定义
touchStart(event) {
let touchPos = event.getLocation();
// 获取当前触摸位置
let posInNode = this.worldConvertLocalPoint(this.node, touchPos);
// 将当前触摸位置坐标转换为世界坐标
let target = this.node.getContentSize();
// 获得当前触摸组件的大小
let rect = cc.rect(0, 0, target.width, target.height);
// 对触摸对象组件创建一个矩形对象
if (rect.contains(posInNode)) {
// 判断触摸的位置是否在矩形内
this.touchTile = this.node;
// 获取被触摸的对象
}
console.log(posInNode.x + " " + posInNode.y);
// 测试,打印当前触摸位置
},
touchMove(event) {
if (this.touchTile) {
this.touchTile.setPosition(this.touchTile.x + event.getDelta().x ,
this.touchTile.y + event.getDelta().y);
// 根据小车组件移动距离重新给小车定位
}
},
touchEnd(event) {
let touchPos = this.touchTile.convertToWorldSpaceAR(cc.v2(0, 0));
let posInNode = this.worldConvertLocalPoint(this.sense1, touchPos);
let target = this.sense1.getContentSize();
// 定义坐标修正值
let correctValue = cc.v2(this.sense.width / 2 - this.origin.x - this.node.width / 2, this.sense.height / 2 - this.origin.y - this.node.height / 2);
// 获取要置放的区域的大小
let rect = cc.rect(0, 0, target.width, target.height);
if (rect.contains(posInNode)) {
// 判断小车是否落在目标区域的矩形内
console.log("---endPos");
// 设置触摸结束后小车的落位坐标
let targetPos = this.sense1.convertToWorldSpace(cc.v2(correctValue));
// 获取目标区域的中心坐标
let action = cc.moveTo(0.3, targetPos);
// 新建一个位移动作,动画持续时间为0.3s
this.touchTile.runAction(action);
// 小车组件执行动作
} else {
console.log("----go back");
let action = cc.moveTo(0.3, this.carPos);
// 组件回到小车初始位置
this.touchTile.runAction(action);
}
this.touchTile = null;
// 重置触摸组件为空
},
worldConvertLocalPoint(node, worldPoint) {
if (node) {
return node.convertToNodeSpace(worldPoint);
}
return null;
}
最终效果
拖入目标区域

没拖到指定区域

修正
这里要把小车放到目标区域的正中心,需要对坐标进行修正。在cocos creator里,有节点坐标和世界坐标这两个概念

而在属性检查器里,我们所设置的position,也就是锚点的位置,是相对于父节点的,例如图中我把position设为0和0,就是相对于父节点,该组件定位在父节点的几何中心。

那么,哪些坐标值和最终放置的位置坐标有关联呢?
- 小车初始坐标值
- 小车组件的长宽
- 目标区域的长宽
在没有修正之前,把targetPos的值设为this.sense.convertToWorldSpace(cc.v2(0, 0)),拖动后的效果如下图

并且log打印目标位置的坐标,水平值离屏幕宽度一半还有一定的差距,这时我又打印了拖动结束后小车的坐标值,好家伙,我轻点小车没有拖动,控制台输出的坐标值为(0,0),而图中很明显,小车的位置不在世界坐标的原点上,即此时小车的坐标参照点为小车的初始位置
那问题来了,怎么修正?
只需在onload()中定义一个变量储存小车的世界坐标值
this.origin = this.node.convertToWorldSpace(cc.v2(0, 0)),然后在touchEnd()中新定义一个向量值correctValue,新建一个向量cc.v2(-this.origin.x, -this.origin.y),并返回给correctValue,再将correctValue转化为世界坐标赋给targetPos,此时小车会自动吸附到目标区域左下角,展现的效果如下

如果要把小车定位到目标区域的正中央,还需要考虑小车组件和目标区域的长宽,相应地,correctValue应该设为cc.v2(this.sense.width / 2 - this.node.width / 2 - this.origin.x, this.sense.height / 2 - this.node.height / 2 - this.origin.y)
参考链接
(61条消息) CocosCreator的拖动小游戏主要逻辑_天才派大星 !的博客-CSDN博客_cocos creator 拖动
原文出处:cocos2d拖动组件吸附效果 | Jayden's Blog (jaydenchang.top)
在Cocos2d中拖动组件并吸附到节点的更多相关文章
- [置顶] Flex中Tree组件无刷新删除节点
在Tree组件中经常要删除某个节点,而删除之后重新刷新加载该Tree组件会影响整个操作效果和效率,因此,无刷新删除就比较好,既删除了节点也没有刷新tree,而使Tree的状态处于删除之前的状态. 无刷 ...
- 第一百九十三节,jQuery EasyUI,Draggable(拖动)组件
Draggable(拖动)组件 学习要点: 1.加载方式 2.属性列表 3.事件列表 4.方法列表 本节课重点了解 EasyUI 中 Draggable(拖动)组件的使用方法,这个组件不依赖于其 他组 ...
- 微信开发新增拖动组件--movableview介绍
小程序的更新中,也新增了一个UI组件,它就是视图组件movable-view,它需要配合movable-area来一起使用.简单来说,它就是一个支持在指定区域内可以拖动内容的容器.我们来看一个简单的示 ...
- [刘阳Java]_easyui-draggable拖动组件_第4讲
easyui-draggable的拖动组件还是比较好用的,它能够快速地实现网页中元素的拖动效果 实现easyui-draggable拖动组件有两种方式:纯HTML方式和JS方式 纯HTML方式实现拖动 ...
- android中四大组件之间相互通信
好久没有写有关android有关的博客了,今天主要来谈一谈android中四大组件.首先,接触android的人,都应该知道android中有四大组件,activity,service,broadca ...
- Android ScrollView中的组件设置android:layout_height="fill_parent"不起作用的解决办法
例子,在ScrollView下加入的组件,无论如何也不能自动扩展到屏幕高度. 布局文件. [html] <?xml version="1.0" encoding=" ...
- 如何在Vue2中实现组件props双向绑定
Vue学习笔记-3 前言 Vue 2.x相比较Vue 1.x而言,升级变化除了实现了Virtual-Dom以外,给使用者最大不适就是移除的组件的props的双向绑定功能. 以往在Vue1.x中利用pr ...
- cocos2d中的可见性检测
游戏的在进行一次渲染的时候,通常会提交大量的渲染对象给gpu.在这些需要渲染的对象中,并不是所有对象都会出现镜头中,即有一部分对象是不可见的. 通常有两种方式来完成不可见对象的剔除工作: (1)直接交 ...
- java中解决组件重叠的问题(例如鼠标移动组件时)
java中解决组件覆盖的问题! 有时候在移动组件的时候会出现两个组件覆盖的情况,但是你想让被覆盖的组件显示出来或者不被覆盖! 在设计GUI时已经可以定义组件的叠放次序了(按摆放组件的先后顺序) ...
- Cocos2d 中的Sprite大小调整问题
以前用UIImageView,比如 UIImageView *view = [[UIImageViewalloc] initWithImage:[UIImageimageNamed:@"b ...
随机推荐
- 大奖升级!HMS Core线上Codelabs挑战赛第3期:用3D建模构建元宇宙
"元宇宙"概念风生水起,在AR.VR等技术构建的虚拟世界里,3D模型担当重要角色,无论是为玩家提供更丰富更真实游戏体验的3D游戏领域,还是各大电商平台正在启用并不断完善的3D虚拟购 ...
- Stable diffusion 初学者指南
1. Stable diffusion 初学者指南 想掌握Stable Diffusion AI技术吗? 这份初学者指南专为完全没接触过Stable Diffusion或任何AI图像生成器的新手设计. ...
- MogDB/openGauss 坏块测试-对启动的影响-测试笔记1
MogDB/openGauss 坏块测试-对启动的影响-测试笔记 1 在 UPDATE 操作提交后,脏块落盘前 kill 掉 mogdb 数据库,然后对 UPDATE 修改的坏进行以下破坏操作,仍然能 ...
- 开发指导—利用组件&插值器动画实现HarmonyOS动效
一. 组件动画 在组件上创建和运行动画的快捷方式.具体用法请参考通用方法. 获取动画对象 通过调用animate方法获得animation对象,animation对象支持动画属性.动画方法和动画事件. ...
- BZOJ 4403序列统计
假设存在一个满足条件的长度为i的不下降序列(显然是一定存在的)那么只需要从中选出i个数即可 (不必在意选出具体数的大小,可以把满足条件的序列写下来,选几个数感受一下). 但是$n \choose m ...
- redis 简单整理——redis 的集合基本结构和命令[五]
前言 简单介绍一下集合的基本结构和命令. 正文 集合(set)类型也是用来保存多个的字符串元素,但和列表类型不一 样的是,集合中不允许有重复元素,并且集合中的元素是无序的,不能通过 索引下标获取元素. ...
- 重新整理数据结构与算法(c#)——KMP破解[二十七]
前言 很多人把KMP和暴力破解分开,其实KMP就是暴力破解,整个高大上的名字,难道还不是去试错匹配吗? KMP是这样子的,比如说: 绿色部分是我要匹配的. 按照一般写法是这样子的: ABABA 去匹配 ...
- 吴恩达机器学习课后作业ex1
题目大体意思就是输入的是某地的人口,输出的是某地方的收益. 题目及数据集下载: https://wwa.lanzous.com/b054sprza 密码:ba3w 大体模型如下图:现在X前边加一列值为 ...
- 实训篇-Html-超链接练习
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- 通过UI自动化方式获取文章、视频信息
出于学习研究,对某账号的文章.视频分析一翻,尝试使用自动化方式看能否获取相应信息. 获取某号的文章有多重方法: 第一种是通过搜狗浏览器搜索账号(这种方式每天只能获取一篇文章,基本上没啥用.): 第二种 ...