在Cocos2d中拖动组件并吸附到节点

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

properties里新建一个对象,用来接收目标区域的节点

然后在小车节点里绑定这个脚本,将要测试的目标节点拖动到属性检查器的 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)

Original: https://www.cnblogs.com/jaydenchang/p/15912721.html
Author: JaydenChang
Title: 在Cocos2d中拖动组件并吸附到节点

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/585156/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • Nginx总结(九)Nginx服务器高性能优化的配置–轻松实现10万并发访问量

    前面讲了如何配置Nginx虚拟主机,如何配置服务日志等很多基础的内容,大家可以去这里看看nginx系列文章:https://www.cnblogs.com/zhangweizhon…

    Java 2023年5月30日
    058
  • Spring 整合Mybatis dao原始方法

    先看一下项目图,基本就理解了整合的内容 这次主角不再是Mybats的配置文件SqlMapConfig.xml了,而是Spring的applicationContext.xml ap…

    Java 2023年5月30日
    078
  • 初识ServletJSPJavaBean

    通过网络资料的介绍,初步对Servlet、JSP和JavaBean有了感性认知,暂且小结如下: 1三者的概念 Servlet:Server Applet小服务程序 JSP:Java…

    Java 2023年5月29日
    072
  • 加深对AQS原理的理解示例一:实现一个独占锁

    基于AQS语法自己定义的独占锁 只是一个简单的版本,非常粗糙,只为了加深对AQS原理理解。但还有一些列问题有待解决,比如锁的重入,锁不允许被其他线程中断等! /** *@Desc …

    Java 2023年6月15日
    074
  • postmassage用法

    1、主页面 allow=”camera ; microphone “作用是开放音频权限 <template> <section class…

    Java 2023年6月8日
    070
  • Java学习-第一部分-第二阶段-第三节:异常

    异常 笔记目录:(https://www.cnblogs.com/wenjie2000/p/16378441.html) 运行下面的代码,看看有什么问题->引出异常和异常处理…

    Java 2023年6月16日
    096
  • IDEA远程部署项目到Docker

    最近在写东西部署到服务器,结构是springboot工程配合docker部署。但是每次部署都3个步骤: 部署次数一多,我就怀疑人生了。就在找有没有IDEA远程部署Docker的方案…

    Java 2023年6月16日
    080
  • .net ElasticSearch-Sql 扩展类【原创】

    官方提供的是java sdk,并支持jdbc方式的查询结果输出;但是却没有.net sdk的支持。 开发 ElasticSearch-Sql 第三方开源项目的.net sdk,未来…

    Java 2023年6月8日
    072
  • MySQL的主从复制和分库分表初探

    主从复制 + 分库分表 要讲主从复制,首先来看看MySQL自带的日志文件。 日志 错误日志 错误日志是 MySQL 中最重要的日志之一,它记录了当 mysqld 启动和停止时,以及…

    Java 2023年6月15日
    070
  • 用过Redis吗,它使用在哪些地方(使用场景)?

    1. 用过Redis吗,它使用在哪些地方(使用场景)? Redis是一种内存型数据库,用作数据库,缓存和消息代理。数据结构简单,读写速度快(毫秒级),原子操作。适用于: 数据高并发…

    Java 2023年6月15日
    072
  • centos7.5安装Oracle11gR2

    centos7.5安装Oracle11gR2 说明:由于上一台旧的笔记本电脑(CPU:i5-7200,内存:8G,硬盘:128SSD+1T机械)卸任,所以打算在家搭建一个个人服务器…

    Java 2023年6月8日
    070
  • redis的三种特殊数据类型

    Redis 在 2.8.9 版本添加了 HyperLogLog 结构。 Redis HyperLogLog 是用来做基数(集合中不重复的数)统计的算法,HyperLogLog 的优…

    Java 2023年6月5日
    074
  • Nginx:rewrite 的几个技巧

    在软件的发布中,我们经常会使用到 Nginx,Nginx 的功能非常的庞杂,其中 rewrite 是一个非常常用的功能模块,本文介绍 rewrite 的基本概念和几个小技巧。 re…

    Java 2023年5月30日
    080
  • 11.Feign面试点及实战优化

    Feign之HTTP性能优化 Feign默认使用的JDK自带的HTTP方式 Feign最大的优化点是更换HTTP底层实现 目前Apache HTTPClient是一个非常好的选择 …

    Java 2023年6月8日
    057
  • leetcode 144. Binary Tree Preorder Traversal 二叉树展开为链表(中等)

    一、题目大意 给你二叉树的根节点 root ,返回它节点值的 前序 遍历。 示例 1: 输入:root = [1,null,2,3]输出:[1,2,3] 示例 2: 输入:root…

    Java 2023年6月14日
    071
  • 方法的深度理解

    权限修饰符 返回值类型 类名(行参列表 )throws 异常的类型{ //方法体 约定俗称:子类中叫重写的方法,父类中叫被重写的方法。 ①子类重写的方法名和行参列表和父类被重写的方…

    Java 2023年6月7日
    074
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球