当前位置: 首页 > article >正文

【CocosCreator 3.x】实现物体按指定轨迹移动

效果图

请添加图片描述

思路

物体按指定轨道运动的话,轨道用多边形表示。

物体沿着多边形上的边移动,顺序地从一个点移动到下一个点。

将曲线运动简化成直线运动。

物体运动的距离用 t t t表示,线段用向量表示。比如点 a ⃗ ( 0 , 0 ) \vec{a}(0, 0) a (0,0)和点 b ⃗ ( 2 , − 1 ) \vec{b}(2, -1) b (2,1)连成的线段用向量 b ⃗ − a ⃗ = ( 2 , − 1 ) \vec{b} - \vec{a} = (2, -1) b a =(2,1)表示。

算出多边形每一线段的长度,依次遍历并累减,得出 t t t当前在哪一条线段上,并得出 t t t在累减遍历过的线段长度后,剩余的长度 s s s

将长度 s s s除以当前线段长度得出线段向量的缩放比例。乘以线段向量 b ⃗ − a ⃗ \vec{b} - \vec{a} b a ,得出当前点相对该线段起始点 ( 2 , − 1 ) (2, -1) (2,1)的偏移量。将该偏移量加上线段起始点的向量 ( 2 , − 1 ) (2, -1) (2,1)得出当前点的坐标向量。
请添加图片描述

代码实现

多边形的代码实现:

import { assert, Vec3 } from "cc";

/**
 * 多边形
 */
export class Polygon {
    /** 点集 */
    points: Vec3[] = [];
    /** 线段长度集 */
    private lengths: number[] = [];
    /** 总长度 */
    private totalLength: number = 0;
    /** 线段向量 */
    private lines: Vec3[] = [];

    constructor(points: Vec3[]) {
        this.points = points;
        this.init();
    }

    /**
     * 初始化线段信息
     */ 
    init() {
        assert(!!this.points && this.points.length > 1, "The number of points must greater than 1.");
        /** 遍历线段 */
        for (let i = 0; i < this.points.length - 1; i++) {
            // 每段线段的长度
            let lindLength = Vec3.distance(this.points[i], this.points[i + 1]);
            this.lengths.push(lindLength);
            // 总长度累加
            this.totalLength += lindLength;
            // 得出两点的线段向量
            this.lines.push(Vec3.subtract(new Vec3(), this.points[i + 1], this.points[i]));
        }
    }

    /**
     * 根据距离参数获取多边形边上的点位置
     * @param curLength 当前长度
     * @returns 当前点所在多边形边上的位置
     */
    getPoint(curLength: number): [number, Vec3] {
        // 对当前长度取余,以免溢出
        curLength %= this.totalLength;
        // 保存取余后的长度
        let newLength = curLength;
        // 遍历线段
        for (let i = 0; i < this.lengths.length; i++)  {
            if (curLength < this.lengths[i]) {
                // 当前长度与线段长度的比例
                let ratio = curLength / this.lengths[i];
                // 当前线段向量
                let line = this.lines[i];
                // 在当前线段上的长度/总线段长度乘以线段向量,得出当前坐标
                return [newLength, Vec3.add(new Vec3(), this.points[i], Vec3.multiplyScalar(new Vec3(), line, ratio))];
            } else {
                // 当前长度减去线段长度
                curLength -= this.lengths[i];
            }
        }
        throw new Error("Cannot find the line point");
    }
}

轨道的代码:

import { _decorator, Component, Vec3 } from 'cc';
import { Polygon } from './framework/Polygon';
const { ccclass, property } = _decorator;

/**
 * 轨道
 */
@ccclass('Orbit')
export class Orbit extends Component {
    /** 轨道点集 */
    @property(Vec3)
    points: Vec3[] = [];
    /** 运动速度 */
    @property
    speed: number = 10;

    /** 多边形轨道 */
    private polygon: Polygon = null;

    /** 当前遍历长度 */
    private curLength: number = 0;

    protected onLoad(): void {
        // 初始化多边形
        this.polygon = new Polygon(this.points);
    }
    
    start() {
        // 初始化位置
        this.refreshPosition(0);
    }

    update(deltaTime: number) {
        // 更新位置
        this.refreshPosition(deltaTime);
    }

    /** 
     * 刷新位置
     * @param deltaTime 帧间隔时间
     */
    refreshPosition(deltaTime: number) {
        // 当前长度累加帧间间隔时间乘以速度
        this.curLength += deltaTime * this.speed;
        let curPosition = null;
        // 获取当前位置
        [this.curLength, curPosition] = this.polygon.getPoint(this.curLength);
        // 设置当前位置
        this.node.setPosition(curPosition);
    }
}

http://www.kler.cn/news/330659.html

相关文章:

  • python开源代码自学问题解决(requests+openpyxl+pymysql)
  • 云栖实录 | 开源大数据全面升级:Native 核心引擎、Serverless 化、湖仓架构引领云上大数据发展
  • 【笔记】1.4.4断裂判据
  • 分布式理论:拜占庭将军问题
  • 计算机视觉周边技术解析:从基础到前沿
  • 【算法】DFS 系列之 穷举/暴搜/深搜/回溯/剪枝(上篇)
  • (作业)第三期书生·浦语大模型实战营(十一卷王场)--书生入门岛通关第3关Git 基础知识
  • fish-speech语音大模型本地部署
  • python you-get下载视频
  • 【当当网】电子书城-02-验证码的实现
  • 汽车制动系统详解
  • AQS原理(AbstractQueuedSynchronizer)
  • 简单的springboot 编写Socket服务接口
  • 计算机网络各层有哪些协议?计算机网络协议解析:从拟定到实现,全面了解各层协议的作用与区别
  • 重生之我们在ES顶端相遇第 19 章 - 综合排序(进阶),打造你的个性化排序
  • 工具笔记之生成图表和可视化的标记语言Mermaid
  • WPF后台创建控件和绑定
  • uniapp中在web端如何友好的展示app当前的版本等信息
  • 知识图谱入门——6:Cypher 查询语言高级组合用法(查询链式操作、复杂路径匹配、条件逻辑、动态模式创建,以及通过事务控制和性能优化处理大规模数据。
  • Python | Leetcode Python题解之第445题两数相加II