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

2024-04-12 12:20

本文主要是介绍【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].posdata.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 = moveSpeedif (pointArr.length * moveSpeed > time) speed = (time / pointArr.length)// if (speed > moveSpeed) speed = moveSpeedpointArr.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) {}
}

这篇关于【cocos creator】【TS】贝塞尔曲线,地图之间显示曲线,顺着曲线移动的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/897115

相关文章

Vue中组件之间传值的六种方式(完整版)

《Vue中组件之间传值的六种方式(完整版)》组件是vue.js最强大的功能之一,而组件实例的作用域是相互独立的,这就意味着不同组件之间的数据无法相互引用,针对不同的使用场景,如何选择行之有效的通信方式... 目录前言方法一、props/$emit1.父组件向子组件传值2.子组件向父组件传值(通过事件形式)方

Python实现PDF与多种图片格式之间互转(PNG, JPG, BMP, EMF, SVG)

《Python实现PDF与多种图片格式之间互转(PNG,JPG,BMP,EMF,SVG)》PDF和图片是我们日常生活和工作中常用的文件格式,有时候,我们可能需要将PDF和图片进行格式互转来满足... 目录一、介绍二、安装python库三、Python实现多种图片格式转PDF1、单张图片转换为PDF2、多张图

使用Folium在Python中进行地图可视化的操作指南

《使用Folium在Python中进行地图可视化的操作指南》在数据分析和可视化领域,地图可视化是一项非常重要的技能,它能够帮助我们更直观地理解和展示地理空间数据,Folium是一个基于Python的地... 目录引言一、Folium简介与安装1. Folium简介2. 安装Folium二、基础使用1. 创建

Qt把文件夹从A移动到B的实现示例

《Qt把文件夹从A移动到B的实现示例》本文主要介绍了Qt把文件夹从A移动到B的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学... 目录如何移动一个文件? 如何移动文件夹(包含里面的全部内容):如何删除文件夹:QT 文件复制,移动(

Linux虚拟机不显示IP地址的解决方法(亲测有效)

《Linux虚拟机不显示IP地址的解决方法(亲测有效)》本文主要介绍了通过VMware新装的Linux系统没有IP地址的解决方法,主要步骤包括:关闭虚拟机、打开VM虚拟网络编辑器、还原VMnet8或修... 目录前言步骤0.问题情况1.关闭虚拟机2.China编程打开VM虚拟网络编辑器3.1 方法一:点击还原VM

CSS模拟 html 的 title 属性(鼠标悬浮显示提示文字效果)

《CSS模拟html的title属性(鼠标悬浮显示提示文字效果)》:本文主要介绍了如何使用CSS模拟HTML的title属性,通过鼠标悬浮显示提示文字效果,通过设置`.tipBox`和`.tipBox.tipContent`的样式,实现了提示内容的隐藏和显示,详细内容请阅读本文,希望能对你有所帮助... 效

Java对象和JSON字符串之间的转换方法(全网最清晰)

《Java对象和JSON字符串之间的转换方法(全网最清晰)》:本文主要介绍如何在Java中使用Jackson库将对象转换为JSON字符串,并提供了一个简单的工具类示例,该工具类支持基本的转换功能,... 目录前言1. 引入 Jackson 依赖2. 创建 jsON 工具类3. 使用示例转换 Java 对象为

Python重命名文件并移动到对应文件夹

《Python重命名文件并移动到对应文件夹》在日常的文件管理和处理过程中,我们可能会遇到需要将文件整理到不同文件夹中的需求,下面我们就来看看如何使用Python实现重命名文件并移动到对应文件夹吧... 目录检查并删除空文件夹1. 基本需求2. 实现代码解析3. 代码解释4. 代码执行结果5. 总结方法补充在

java父子线程之间实现共享传递数据

《java父子线程之间实现共享传递数据》本文介绍了Java中父子线程间共享传递数据的几种方法,包括ThreadLocal变量、并发集合和内存队列或消息队列,并提醒注意并发安全问题... 目录通过 ThreadLocal 变量共享数据通过并发集合共享数据通过内存队列或消息队列共享数据注意并发安全问题总结在 J

Java文件与Base64之间的转化方式

《Java文件与Base64之间的转化方式》这篇文章介绍了如何使用Java将文件(如图片、视频)转换为Base64编码,以及如何将Base64编码转换回文件,通过提供具体的工具类实现,作者希望帮助读者... 目录Java文件与Base64之间的转化1、文件转Base64工具类2、Base64转文件工具类3、