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

代码实现

定义节点和函数功能

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. 怎么查看摄像头的硬件ID

    1.打开设备管理器:电脑桌面左下角Windows图标点击鼠标右键,点击[设备管理器] 2.展开[照相机] 3.双击摄像头,弹出属性框 4.点击[详细信息],属性点击[硬件ID]

  2. 【资料包】HDC.Together 2023精选Codelabs指南现已上线(内有活动)

     今年HDC.Together 2023的Codelabs挑战系列活动如期而至,众多开发者齐聚一堂,积极参与.本次赛题中部分Codelabs已在官网上线详细操作指南,让我们与众多coders一起探索代 ...

  3. 重新点亮shell————awk函数[十五]

    前言 简单介绍一下awk函数. 正文 算术函数 字符串函数 自定义函数 例子: 结 awk就到这里了.

  4. 一个.NET开源的功能丰富、灵活易用的 Windows 窗口增强神器

    前言 通常情况下 Windows 中的软件窗口界面一般只包含还原.移动.大小.最大化.最小化.关闭等几个基本的操作: 今天大姚给大家推荐一个.NET开源.免费(MIT License).功能丰富.灵活 ...

  5. PIL.Image, numpy, tensor, cv2 之间的互转,以及在cv2在图片上画各种形状的线

    ''' PIL.Image, numpy, tensor, cv2 之间的互转 ''' import cv2 import torch from PIL import Image import num ...

  6. lattice的ip不显示,如何解决

    最近ip服务器可能会遇到问题,建议客户把更新检查关掉.我们有对应的IP下载链接.   diamond在     https://www.latticesemi.com/ispupdate/ipexpr ...

  7. 通过一个非常简单的SSM项目来将SpringMVC配置整理清晰。

    所有的文件在Git上面都能找到,由于把代码搞上来看的很不舒服,结构不清晰. 第一步:确定环境 IDEA MySQL 5.7.19 Tomcat 9 Maven 3.6 第二步:创建数据库 参考GIT上 ...

  8. 了解3D世界的黑魔法-纯Java构造一个简单的3D渲染引擎

    简介: 对于非渲染引擎相关工作的开发者来说,可能认为即使构建最简单的3D程序也非常困难,但事实上并非如此,本篇文章将通过简单的200多行的纯 Java代码,去实践正交投影.简单三角形光栅化.z缓冲(深 ...

  9. 动态尺寸模型优化实践之Shape Constraint IR Part I

    简介: 在本系列分享中我们将介绍BladeDISC在动态shape语义下做性能优化的一些实践和思考.本次分享的是我们最近开展的有关shape constraint IR的工作,Part I 中我们将介 ...

  10. 一遇到复杂分析查询就卡顿?MySQL分析实例了解一下

    随着企业数据爆发式增长,MySQL分析查询卡顿问题越来越多,用户时效性不能保证,精细化运营诉求不能满足.如何能无缝对接业务库,实现毫秒级针对万亿级数据进行即时的多维分析透视和业务探索,MySQL分析实 ...