【cocos creator】【TS】贝塞尔曲线,地图之间显示曲线,顺着曲线移动

参考:
https://blog.csdn.net/Ctrls_/article/details/108731313
https://blog.csdn.net/qq_28299311/article/details/104009804
在这里插入图片描述

在这里插入图片描述



const { ccclass, property } = cc._decorator;

@ccclass
export default class mapPanel extends cc.Component {
    @property(cc.Node)
    player: cc.Node = null;
    @property(cc.Node)
    build: cc.Node = null;
    @property(cc.Node)
    point: cc.Node = null;
    @property(cc.Node)
    root: cc.Node = null;

    start() {
        this.init();
    }

    init(data?) {
        data = {
            mapData: [
                { id: 1, name: "1", pos: { x: 0, y: 100 } },
                { id: 2, name: "2", pos: { x: -100, y: -100 } },
                { id: 3, name: "3", pos: { x: 200, y: -80 } },
                { id: 4, name: "4", pos: { x: 180, y: 300 } },
                { id: 5, name: "5", pos: { x: 150, y: 50 } }
            ],
            linkData: [[2, 1], [1, 4], [5, 1], [5, 3], [2, 5]],
            startPosId: 2,
            road: [2, 5, 1, 4]
        }
        data.mapData.forEach(element => {
            this.creatOneBuild(element, data.startPosId)
        });
        this.player.position = data.mapData[data.startPosId - 1].pos
        data.linkData.forEach(element => {
            this.setPoint(cc.v2(data.mapData[element[0] - 1].pos), cc.v2(data.mapData[element[1] - 1].pos))
        });
        let roadArray = []
        data.road.forEach((element) => {
            roadArray.push(data.mapData[element - 1].pos);
        })
        this.playTween(roadArray);
    }

    playTween(roadArray, moveSpeed = 0.003, time = 1.5, delayTime = 0.3, cb?) {
        let tween = cc.tween(this.player)
        let nowPos = roadArray[0]
        for (let i = 1; i < roadArray.length; i++) {
            let nextPos = roadArray[i]
            let pointArr = this.getOneroad(nowPos, nextPos, 1)
            let speed = moveSpeed
            if (pointArr.length * moveSpeed > time) speed = (time / pointArr.length)
            // if (speed > moveSpeed) speed = moveSpeed
            pointArr.forEach(element => {
                tween.to(speed, { position: element })
            });
            tween.delay(delayTime)
            nowPos = nextPos;
        }
        tween
            .call(() => {
                cb && cb()
            })
            .start();
    }

    creatOneBuild(data, nowId) {
        let build = cc.instantiate(this.build);
        build.parent = this.root;
        build.position = cc.v3(data.pos);
        build.getChildByName("name").getComponent(cc.Label).string = data.name;
        build.active = true;
        build.getChildByName("light").active = nowId == data.id;
    }

    creatOnePoint(pos: cc.Vec3) {
        let build = cc.instantiate(this.point);
        build.parent = this.root;
        build.position = pos;
        build.active = true;
    }


    /**
     * 设置点
     * @param startPoint 起点
     * @param endPoint 终点
     * @param pointDistance 小点间距
     * @param angel 弧度
     */
    setPoint(startPoint, endPoint, pointDistance = 30, angel = 60) {
        let pointArr = this.getOneroad(startPoint, endPoint, pointDistance, angel)
        pointArr.forEach(element => {
            this.creatOnePoint(element)
            console.log(element);//每个小圆点点坐标,这里进行处理
        });
    }

    /**
     * 获取n点之间路径
     * @param startPoint 起点
     * @param endPoint 终点
     * @param pointDistance 小点间距
     * @param angel 弧度
     */
    getTotalRoad(arrList, pointDistance = 30, angel = 60) {
        let pointArrTotal = []
        let nowPos = pointArrTotal.shift()
        let list = arrList;
        while (1) {
            let nextPos = list.shift()
            if (nextPos) {
                let pointArr = this.getOneroad(nowPos, nextPos, pointDistance, angel)
                pointArrTotal = pointArrTotal.concat(pointArr)
                nowPos = nextPos;
            }
            else {
                break;
            }
        }
        return pointArrTotal
    }
    /**
     * 获取两点之间路径
     * @param startPoint 起点
     * @param endPoint 终点
     * @param pointDistance 小点间距
     * @param angel 弧度
     */
    getOneroad(startPoint, endPoint, pointDistance = 30, angel = 60) {
        startPoint = cc.v2(startPoint);
        endPoint = cc.v2(endPoint);
        let distance = startPoint.sub(endPoint).mag();
        let middlePoint = cc.v2((startPoint.x + endPoint.x) / 2, (startPoint.y + endPoint.y) / 2)
        let height = Math.sin(angel * (180 / Math.PI)) * (distance / 2) * 1.5;
        cc.log(height)
        let middlePoint2 = this.findPointCInRightTriangle(startPoint, middlePoint, height);
        let number = Number((distance / pointDistance).toFixed(0));
        let pointArr = this.getBezierPoints(number, startPoint, height ? middlePoint2 : middlePoint, endPoint)
        return pointArr;
    }

    /**
     * 获取两点之间垂直平分线线上的点
     * @param startPoint 
     * @param endPoint 
     * @param bcLength 
     * @returns 
     */
    findPointCInRightTriangle(startPoint: cc.Vec2, endPoint: cc.Vec2, bcLength: number, isUP = true): cc.Vec2 | null {
        let ax = endPoint.x;
        let ay = endPoint.y;
        let bx = startPoint.x;
        let by = startPoint.y;
        // 计算向量AB  
        const dx = bx - ax;
        const dy = by - ay;

        // 计算AB的长度  
        const abLength = Math.sqrt(dx * dx + dy * dy);

        // 检查AB长度是否为零,以避免除以零的错误  
        if (abLength === 0) {
            return null; // 无法确定C点位置,因为AB长度为0  
        }

        // 计算AC的长度(利用勾股定理)  
        const acLength = Math.sqrt(bcLength * bcLength - abLength * abLength);

        // 计算向量AB的单位向量  
        const abUnitX = dx / abLength;
        const abUnitY = dy / abLength;

        // 计算向量AC,它垂直于向量AB(因为ABC是直角三角形)  
        const acUnitX = -abUnitY; // 垂直向量的x分量是原向量y分量的相反数  
        const acUnitY = abUnitX;  // 垂直向量的y分量是原向量x分量  

        // 计算点C的坐标  
        const cx = ax + acLength * acUnitX * (isUP ? -1 : 1);
        const cy = ay + acLength * acUnitY * (isUP ? -1 : 1);

        return cc.v2(cx, cy);
    }
    /**
    * 获取贝塞尔曲线上的点
    * @param {返回的点的数组长度} num 
    * @param {起点} startPoint 
    * @param {控制点} middlePoint 
    * @param {终点} endPoint 
    */
    getBezierPoints(num, startPoint, middlePoint, endPoint) {
        let pointList = [];
        let x1 = startPoint.x, y1 = startPoint.y;
        let x2 = endPoint.x, y2 = endPoint.y;
        let cx = middlePoint.x, cy = middlePoint.y;
        let t = 0;
        for (let i = 1; i < (num + 1); i++) {
            //用i当作t,算出点坐标,放入数组
            t = i / num;
            let x = Math.pow(1 - t, 2) * x1 + 2 * t * (1 - t) * cx + Math.pow(t, 2) * x2;
            let y = Math.pow(1 - t, 2) * y1 + 2 * t * (1 - t) * cy + Math.pow(t, 2) * y2;
            pointList.push(cc.v2(x, y))
        }
        return pointList;
    }

    // update (dt) {}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/536351.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Oracle 常用命令总结

文章目录 一、数据库启动 & 关闭&查看1、启动数据库2、关闭数据库3、连接数据库4、查看数据库名5、查看实例 二、用户1、创建用户2、重置密码3、账户解锁4、账号赋权5、账户撤销权限6、删除用户7、查询所有用户&#xff08;DBA账号执行&#xff09;8、查看当前用户连接…

vue3 依赖-组件tablepage-vue3说明文档,列表页快速开发,使用思路及范例(Ⅰ)配置项文档

配置项API 引入思路介绍TablePage-vue3 API汇总属性插槽Exposes自定义对象searchConfig(array<object\> 类型)searchConfig-type当typetimes时当type不为时间类型时的 bind默认值&#xff08;Object类型&#xff09;当type为时间类型时的 bind默认值&#xff08;Object类…

【MySQL】数据库节点的平滑扩容方案

一、背景 众所周知&#xff0c;数据库很容易成为应用系统的瓶颈。单机数据库的资源和处理能力有限&#xff0c;在高并发的分布式系统中&#xff0c;可采用分库分表突破单机局限。本文来探讨下数据库节点的平滑扩容方案 二、节点扩容 2.1、什么是节点扩容 扩容一般是指水平分…

02 SQL基础 -- 初识SQL

一、初识 SQL 1.1 概念介绍 数据库中存储的表结构类似于 excel 中的行和列,在数据库中,行称为记录,它相当于一条结论,列称为字段,它代表了表中存储的数据项目 行和列交汇的地方称为单元格,一个单元格只能输入一条记录 SQL是为操作数据库而开发的语言。国际标准化组织(…

java数据结构与算法刷题-----LeetCode268. 丢失的数字

java数据结构与算法刷题目录&#xff08;剑指Offer、LeetCode、ACM&#xff09;-----主目录-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/123063846 文章目录 数学位运算 数学 解题思路&#xff1a;时间复杂度O( n n n)&…

EFcore 6 连接oracle19 WinForm vs2022

用EFcore访问Oracle&#xff0c;终于不需要Oracle的什么安装包了&#xff0c;直接在VS2022中就可以轻松搞定。在csdn上看到一哥们的帖子&#xff0c;测试了一下&#xff0c;发现很方便。使用的场景是&#xff1a;VS2022中EFcore6。经过测试&#xff0c;同 Navicat Premium 16比…

【数据可视化包Matplotlib】Matplotlib基本绘图方法

目录 一、Matplotlib绘图的基本流程&#xff08;一&#xff09;最简单的绘图&#xff08;仅指定y的值&#xff09;&#xff08;二&#xff09;更一般的绘图&#xff08;同时指定x和y的值&#xff09;&#xff08;三&#xff09;增加更多的绘图元素 二、布局相关的对象——Figur…

linux文件访问权限理解

目录 一&#xff0c;涉及指令: 二&#xff0c;权限的表示 三&#xff0c;权限命令使用 一&#xff0c;涉及指令: umask chmod chown/chgrp 二&#xff0c;权限的表示 rwx rwx r-x含义: 访问方式: r-可读;w-可写&#xff1b;x-可执行&#xff1b; 访问用户:u-所有者;…

02.cesium中模型和图标加载处理

展示效果&#xff0c;我们期待图标点是根据模型&#xff0c;在模型的上方展示 实现思路&#xff1a; 1.在二维地图和三维地图的加载的高度计算不同&#xff0c;需要判断 2.创建一个BillboardCollection&#xff0c;用来存放图标 3.在三维地图中调用getPointPostion方法&#xf…

314_C++_QT表格的撤销、恢复,可对多行、多item进行撤销、恢复操作

行–删除后的,撤销、恢复图示: 原图示 删除后 撤销操作 恢复操作 item修改后的撤销、恢复 原item 撤销修改 恢复修改 代码: --</

Python八股文:基础知识Part1

1. 不用中间变量交换 a 和 b 这是python非常方便的一个功能可以这样直接交换两个值 2. 可变数据类型字典在for 循环中进行修改 这道题在这里就是让我们去回答输出的内容&#xff0c;这里看似我们是在for循环中每一次加入了都在list中加入了一个字典&#xff0c;然后字典的键值…

神经网络模型底层原理与实现8-BERT

首先介绍什么是自监督学习&#xff1a; 普通的有监督学习是每个x对应有个y&#xff0c;x训练得到y&#xff0c;将y与y作比较&#xff0c;而自监督是没有对应y&#xff0c;直接把一部分样本x作为训练目标x&#xff0c;训练得x后和x对比 bert中如何创造x&#xff1a;以文字处理为…

基于SSM“口腔助手”小程序

采用技术 基于SSM“口腔助手”小程序的设计与实现~ 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringMVCMyBatis 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 页面展示效果 小程序前台首页 注册 保健知识 我的 医生登录成功 后台管理员 …

C#如何用NPOI创建、读取、更新Excel文件

一.获取引用NPOI VS2017&#xff0c;通过Nuget工具包下载NPOI到指定的项目中&#xff0c;如下 二.添加如下命名空间,其中HSSF是操作*.xls文件&#xff0c;XSSF操作*.xlsx文件. using NPOI; using NPOI.SS.UserModel; using NPOI.XSSF.UserModel; using NPOI.HSSF.UserModel; …

【LeetCode】单调栈类题目详解

所有题目均来自于LeetCode&#xff0c;刷题代码使用的Python3版本 单调栈 通常针对一维数组的问题&#xff0c;如果需要寻找一个元素右边或者左边第一个比自己大或者小的元素的位置&#xff0c;就可以使用单调栈&#xff0c;时间复杂度为O(n) 单调栈的本质是空间换时间&#…

泽众Testone自动化测试平台,测试用例支持单个调试执行,同步查看执行日志

泽众Testone自动化测试平台之前版本&#xff0c;测试用例批量和单个执行&#xff0c;必须要通过测试集操作执行&#xff0c;操作略繁琐&#xff0c;我们通过本轮优化升级&#xff0c;测试用例直接可以单个调试执行&#xff0c;同步查看执行日志&#xff0c;操作上去繁就简&…

新能源汽车“价格战”之后,充电桩主板市场将会怎样?

2024年2月底&#xff0c;国内新能源汽车市场开启了一场前所未有的“价格战”↓ 比亚迪率先抛出“王炸”车型——秦PLUS荣耀版和驱逐舰05荣耀版&#xff0c;起售价低至7.98万元&#xff0c;打响了价格战的“第一枪”&#xff0c;引爆了平静的汽车市场。 “电比油低”就此拉开序…

常用API时间Arrays

常用API MATH 代表数学&#xff0c;是一个工具类&#xff0c;里面提供的都是对数据进行操作的一些静态方法。 方法名说明public static int abs(int a)获取参数绝对值public static double ceil(double a)向上取整public static double floor(double a)向下取整public stati…

Python零基础从小白打怪升级中~~~~~~~模块+异常+Pycharm的debug调试

第十节&#xff1a;模块异常Debug 一、Python模块 Python 模块(Module)&#xff0c;是一个 Python 文件&#xff0c;以 .py 结尾&#xff0c;模块能定义函数&#xff0c;类和变量&#xff0c;模块里也能包含可执行的代码。 1、导入模块 导入模块的5中方式 import 模块名fr…

计算机网络知识等汇总补充

计算机网络知识汇总补充 一、四次挥手1、为什么TCP要等待2MSL2、如果说一个系统中&#xff0c;有大量的time_wait和close_wait&#xff0c;会是什么原因&#xff1f; 二、你是怎么解决粘包问题&#xff1f;三、你觉得哪些场景适合redis四、redis的持久化策略五、你会怎么保证my…