最近在学习制作小游戏,要实现一个拖动吸附效果,这里简单实现一下

代码实现

定义节点和函数功能

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中拖动组件并吸附到节点的更多相关文章

  1. [置顶] Flex中Tree组件无刷新删除节点

    在Tree组件中经常要删除某个节点,而删除之后重新刷新加载该Tree组件会影响整个操作效果和效率,因此,无刷新删除就比较好,既删除了节点也没有刷新tree,而使Tree的状态处于删除之前的状态. 无刷 ...

  2. 第一百九十三节,jQuery EasyUI,Draggable(拖动)组件

    Draggable(拖动)组件 学习要点: 1.加载方式 2.属性列表 3.事件列表 4.方法列表 本节课重点了解 EasyUI 中 Draggable(拖动)组件的使用方法,这个组件不依赖于其 他组 ...

  3. 微信开发新增拖动组件--movableview介绍

    小程序的更新中,也新增了一个UI组件,它就是视图组件movable-view,它需要配合movable-area来一起使用.简单来说,它就是一个支持在指定区域内可以拖动内容的容器.我们来看一个简单的示 ...

  4. [刘阳Java]_easyui-draggable拖动组件_第4讲

    easyui-draggable的拖动组件还是比较好用的,它能够快速地实现网页中元素的拖动效果 实现easyui-draggable拖动组件有两种方式:纯HTML方式和JS方式 纯HTML方式实现拖动 ...

  5. android中四大组件之间相互通信

    好久没有写有关android有关的博客了,今天主要来谈一谈android中四大组件.首先,接触android的人,都应该知道android中有四大组件,activity,service,broadca ...

  6. Android ScrollView中的组件设置android:layout_height="fill_parent"不起作用的解决办法

    例子,在ScrollView下加入的组件,无论如何也不能自动扩展到屏幕高度. 布局文件. [html] <?xml version="1.0" encoding=" ...

  7. 如何在Vue2中实现组件props双向绑定

    Vue学习笔记-3 前言 Vue 2.x相比较Vue 1.x而言,升级变化除了实现了Virtual-Dom以外,给使用者最大不适就是移除的组件的props的双向绑定功能. 以往在Vue1.x中利用pr ...

  8. cocos2d中的可见性检测

    游戏的在进行一次渲染的时候,通常会提交大量的渲染对象给gpu.在这些需要渲染的对象中,并不是所有对象都会出现镜头中,即有一部分对象是不可见的. 通常有两种方式来完成不可见对象的剔除工作: (1)直接交 ...

  9. java中解决组件重叠的问题(例如鼠标移动组件时)

    java中解决组件覆盖的问题!     有时候在移动组件的时候会出现两个组件覆盖的情况,但是你想让被覆盖的组件显示出来或者不被覆盖! 在设计GUI时已经可以定义组件的叠放次序了(按摆放组件的先后顺序) ...

  10. Cocos2d 中的Sprite大小调整问题

    以前用UIImageView,比如  UIImageView *view = [[UIImageViewalloc] initWithImage:[UIImageimageNamed:@"b ...

随机推荐

  1. 大奖升级!HMS Core线上Codelabs挑战赛第3期:用3D建模构建元宇宙

    "元宇宙"概念风生水起,在AR.VR等技术构建的虚拟世界里,3D模型担当重要角色,无论是为玩家提供更丰富更真实游戏体验的3D游戏领域,还是各大电商平台正在启用并不断完善的3D虚拟购 ...

  2. Stable diffusion 初学者指南

    1. Stable diffusion 初学者指南 想掌握Stable Diffusion AI技术吗? 这份初学者指南专为完全没接触过Stable Diffusion或任何AI图像生成器的新手设计. ...

  3. MogDB/openGauss 坏块测试-对启动的影响-测试笔记1

    MogDB/openGauss 坏块测试-对启动的影响-测试笔记 1 在 UPDATE 操作提交后,脏块落盘前 kill 掉 mogdb 数据库,然后对 UPDATE 修改的坏进行以下破坏操作,仍然能 ...

  4. 开发指导—利用组件&插值器动画实现HarmonyOS动效

    一. 组件动画 在组件上创建和运行动画的快捷方式.具体用法请参考通用方法. 获取动画对象 通过调用animate方法获得animation对象,animation对象支持动画属性.动画方法和动画事件. ...

  5. BZOJ 4403序列统计

    假设存在一个满足条件的长度为i的不下降序列(显然是一定存在的)那么只需要从中选出i个数即可 (不必在意选出具体数的大小,可以把满足条件的序列写下来,选几个数感受一下). 但是$n \choose m ...

  6. redis 简单整理——redis 的集合基本结构和命令[五]

    前言 简单介绍一下集合的基本结构和命令. 正文 集合(set)类型也是用来保存多个的字符串元素,但和列表类型不一 样的是,集合中不允许有重复元素,并且集合中的元素是无序的,不能通过 索引下标获取元素. ...

  7. 重新整理数据结构与算法(c#)——KMP破解[二十七]

    前言 很多人把KMP和暴力破解分开,其实KMP就是暴力破解,整个高大上的名字,难道还不是去试错匹配吗? KMP是这样子的,比如说: 绿色部分是我要匹配的. 按照一般写法是这样子的: ABABA 去匹配 ...

  8. 吴恩达机器学习课后作业ex1

    题目大体意思就是输入的是某地的人口,输出的是某地方的收益. 题目及数据集下载: https://wwa.lanzous.com/b054sprza 密码:ba3w 大体模型如下图:现在X前边加一列值为 ...

  9. 实训篇-Html-超链接练习

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  10. 通过UI自动化方式获取文章、视频信息

    出于学习研究,对某账号的文章.视频分析一翻,尝试使用自动化方式看能否获取相应信息. 获取某号的文章有多重方法: 第一种是通过搜狗浏览器搜索账号(这种方式每天只能获取一篇文章,基本上没啥用.): 第二种 ...