在CocosCreator的3.x版本中tween实现贝塞尔曲线

使用环境参考

CocosCreator v3.7.3

前情提要

在之前的 2.x 版本中,CocosCreator 关于贝塞尔曲线是内置了 API,可以让节点动画直接使用。但在升级到 tween 实现后,灵活了但没有了现成的贝塞尔曲线的实现方法。需要自己实现一下:

二次贝塞尔曲线(一个控制点的),为了方便观察,我用绘图组件示意了一下路径


import { _decorator, Component, Graphics, Node, tween, v3, Vec3 } from 'cc';

const { ccclass, property } = _decorator;

@ccclass('BTest1')

export class BTest1 extends Component {

    @property(Graphics) graphics: Graphics = null;

    @property(Node) box: Node = null;

    start() {

        // 绘制路径做对比

        this.graphics.moveTo(0, 0);

        this.graphics.quadraticCurveTo(200, 300, 200, 200);

        this.graphics.stroke();

        // 三维空间的缓动

        const quadraticCurve = (t: number, p1: Vec3, cp: Vec3, p2: Vec3, out: Vec3) => {

            out.x = (1 - t) * (1 - t) * p1.x + 2 * t * (1 - t) * cp.x + t * t * p2.x;

            out.y = (1 - t) * (1 - t) * p1.y + 2 * t * (1 - t) * cp.y + t * t * p2.y;

            out.z = (1 - t) * (1 - t) * p1.z + 2 * t * (1 - t) * cp.z + t * t * p2.z;

        }

        const startPos = v3(0, 0, 0);

        const controlPos = v3(2, 3, 0);

        const endPos = v3(2, 2, 0);

        const tempVec3 = v3();

       

        tween(this.box).to(3, { position: endPos }, { onUpdate: (target, ratio) => {

            quadraticCurve(ratio, startPos, controlPos, endPos, tempVec3);

            this.box.setPosition(tempVec3);

        }}).start();

    }

}

接下来是两个控制点的,这个三次贝塞尔的计算公式 CocosCreator 进行了内置,不过是一维的,搞成三维:


import { _decorator, bezier, Component, Graphics, Node, tween, v3, Vec3 } from 'cc';

const { ccclass, property } = _decorator;

@ccclass('BTest1')

export class BTest1 extends Component {

    @property(Graphics) graphics: Graphics = null;

    @property(Node) box: Node = null;

    start() {

        // 绘制路径做对比

        this.graphics.moveTo(0, 0);

        this.graphics.bezierCurveTo(80, 400, 200, 50, 200, 200);

        this.graphics.stroke();

        // 三维空间的缓动

        const bezierCurve = (t: number, p1: Vec3, cp1: Vec3, cp2: Vec3, p2: Vec3, out: Vec3) => {

            out.x = bezier(p1.x, cp1.x, cp2.x, p2.x, t);

            out.y = bezier(p1.y, cp1.y, cp2.y, p2.y, t);

            out.z = bezier(p1.z, cp1.z, cp2.z, p2.z, t);

        }

        const startPos = v3(0, 0, 0);

        const controlPos1 = v3(0.8, 4, 0);

        const controlPos2 = v3(2, 0.5, 0);

        const endPos = v3(2, 2, 0);

        const tempVec3 = v3();

       

        tween(this.box).to(3, { position: endPos }, { onUpdate: (target, ratio) => {

            bezierCurve(ratio, startPos, controlPos1, controlPos2, endPos, tempVec3);

            this.box.setPosition(tempVec3);

        }}).start();

    }

}

总结

将以上方法封装到自己的 Util 中就可以愉快滴使用啦!

我是阔阔,一位喜欢研究的程序员!

个人网站:www.kuokuo666.com

2023!Day Day Up!

10赞

大佬牛逼 :+1: :+1: