左右开口和垂直抛物线分享

这是我参照unity3d的抛物线修改的,写的不好请大家多多包涵。
废话不多说,直接上代码:

/*
 * @Author: David.Huang
 * @Date: 2020-09-25 09:33:51
 * @LastEditTime: 2020-09-25 21:31:49
 * @LastEditors: Please set LastEditors
 * @Description: 抛物线轨迹
 */
import { _decorator, Component, Node, Vec3} from 'cc';
import { MathUtil } from '../../../core/utils/MathUtil';
import { PoolUtil } from '../../../core/utils/PoolUtil';
import { WEAPON_FLY_TYPE } from '../../battle/data/BattleConfig';
import { BaseWeapon } from '../base/BaseWeapon';
const { ccclass, property } = _decorator;

const _tempVec: Vec3 = new Vec3();

@ccclass('ParabolaLocus')
export class ParabolaLocus extends BaseWeapon {


    /** 重力加速度 */
    private _g = -10;
    /** 抛出去的速度,值越大顶点越高 */
    private _shotSpeed: number = 15;
    /** 初速度向量 */
    private _speed: Vec3 = null;
    /** 重力向量 */
    private _gravity: Vec3 = null;
    /** 当前角度 */
    private _currAngle: Vec3 = null;
    private _dTime = 0;
    private _flyType: number = -1;
    private _dir: number = 1;
    private _isMoving: boolean = false;

    onLoad() {
        this._speed = new Vec3();
        this._gravity = new Vec3();
        this._currAngle = new Vec3();
    }

    public launchWeapon(flyType: number, startPos: Vec3, endPos: Vec3): void {
        this.startPos = startPos;
        this.endPos = endPos;
        this._flyType = flyType;
        this._dTime = 0;
        //设置初始位置
        this.node.setWorldPosition(this.startPos);

        //求2点之间的距离
        Vec3.subtract(_tempVec, this.startPos, this.endPos);
        const time = _tempVec.length() / this._shotSpeed;

        this._dir = this._flyType === WEAPON_FLY_TYPE.LEFT_PARABOL ? -1 : 1;
        let offsetX: number, offsetY: number = 0;
        switch (this._flyType) {
            case WEAPON_FLY_TYPE.LINE:
                offsetY = 0.5 * this._g * time;
                break;
            default:
                offsetX = 0.5 * this._g * time * this._dir;
                break;
        }

        //计算初速度
        this._speed = new Vec3((this.endPos.x - this.startPos.x) / time - offsetX, (this.endPos.y - this.startPos.y) / time - offsetY, (this.endPos.z - this.startPos.z) / time);
        //重力初速度为0
        Vec3.zero(this._gravity);
        this._isMoving = true;
    }


    update(dt: number) {
        if (!this._isMoving) return;

        if (this._flyType === WEAPON_FLY_TYPE.LINE) {   //直线抛物线
            this._gravity.y = this._g * (this._dTime += dt);
        } else {    //左右抛物线
            this._gravity.x = this._g * (this._dTime += dt * this._dir);
        }

        //计算抛物线位置
        let pos: Vec3 = this.node.getWorldPosition();
        Vec3.add(_tempVec, this._speed, this._gravity);
        Vec3.multiplyScalar(_tempVec, _tempVec, dt);
        Vec3.add(pos, pos, _tempVec);

        if (this._flyType === WEAPON_FLY_TYPE.LINE) {   //直线抛物线
            this._currAngle.x = Math.atan((this._speed.y + this._gravity.y) / this._speed.z) * MathUtil.Rad2Deg;
        } else {    //左右抛物线
            this._currAngle.y = Math.atan((this._speed.x + this._gravity.x) / this._speed.z) * MathUtil.Rad2Deg;
        }

        this.node.eulerAngles = this._currAngle;
        this.node.setWorldPosition(pos);

        //判断是否达到目标点
        Vec3.subtract(_tempVec, this.endPos, pos);
        if (_tempVec.length() <= 0.3) {
            this.arriveTarget();
        }
    }

    /**
     * 达到目标
     */
    private arriveTarget() {
        this._isMoving = false;
        console.warn('达到终点~~~~~~~~~~~');
        PoolUtil.setNode(this.node);
    }
}
5赞

厉害,学习了

谢谢分享,帮你改了一下版式

mark1

MathUtil.Rad2Deg是什么啊

/** 弧度值转换为角度值 */

public static get Rad2Deg(): number {

    return 360 / (Math.PI * 2);

}

用p1,p2两点向量,旋转90得到中垂线向量,然后用圆形坐标公式,取R距离得到两点中垂线上得点p3,然后用 bezier, p1,p3,p2这样得方式可以控制弧线大小,以及左边弧线和右边弧线