3d抛物线绘制

需求

在弹弓类、投射类游戏中,抛物线的绘制是十分常用的功能需求。

该需求的实现也较为简单,但未实现过的同学或者刚入门3d游戏开发的同学,可能没有确切的实现方法,羽毛就本文给大家浅谈抛物线的实现及实现过程的避坑。

效果

(引用Marbo Toss 游戏截图)

问题分析

由高中物理知识可得,抛物线运动可分解为:

  • 垂直方向y的加速度运动。加速度f方向为垂直向下,大小为g,在游戏中,g可随意指定。
    • Vy =Vy0 + g * t ,Sy =Vy0 * t + 1/2 * g* t * t
  • 水平平面存在x,z两个方向的匀速运动
    • Vx = Vx0, Sx = Vx0 * t
    • Vz = Vz0, Sz = Vz0 * t

因此,我们只需要从t=0时,即发射点开始,在相同时间间隔内绘制轨迹点,当这些离散的点连接起来时,便形成了抛物线。

实现

在程序实现时,可分为一下几个步骤:

  1. 预生成一个包含N个轨迹点Node对象的数组ballCurvelist,并将所有的Node添加为发射点的child节点,active设置为false。
  2. 需要显示抛物线时,更新所有node的active为true,并根据抛物线运动公式计算第N个点间隔dt的x,y,z坐标值,刷新position。

核心代码

  • 初始化
 cc.loader.loadRes(url, (err, prefab) => {
            if (err == null) {
                let ballItem = cc.instantiate(prefab);
                for (let count = 0; count < curvePointNum; count++) {
                    let ball: Node = cc.instantiate(ballItem);
                    ball.active = false;
                    this.node.addChild(ball);
                    this.ballCurveList.push(ball);
                }
            } else {
                console.log("加载错误", url);
            }
        });
复制代码
  • 描绘抛物线
    public showCurve(startPos: Vec3, startSpeed: Vec3) {
        var dx = startPos.x;
        var dy = startPos.y;
        var dz = startPos.z;

        const dt = this.deltaTime;
        for (var count = 0; count < this.ballCurveList.length; count++) {
         //每个点的坐标都是上一个点坐标加上位移值
            dx += startSpeed.x * dt;
            dz += startSpeed.z * dt;
            dy += startSpeed.y * dt + 0.5 * this.gravityY * dt * dt;
            let ball = this.ballCurveList[count];
            ball.active = true;
            ball.setWorldPosition(dx, dy, dz);
        }
    }
复制代码

注意的点

为了使小球运动轨迹与轨迹线一直,通过变换速度信息控制小球的运动。update中每帧使用与画轨迹球相同的dt计算小球的实时位置。

private curPos: Vec3 = null;
    update(dt: number) {
        dt = this.deltaTime;
         //点击发射,并且未碰撞目标体的情况下一直保持运动
        if (this.isFire && !this.isCollider) { 
            if (this.curPos == null) {
                this.curPos = this.node.getWorldPosition().clone();
            }
            this.curPos.x += dt * this.dirSpeed.x;
            this.curPos.y += dt * this.dirSpeed.y + this.gravityY * dt * dt / 2;
            this.curPos.z += dt * this.dirSpeed.z;
            this.node.setWorldPosition(this.curPos);
        }
    }
复制代码

小结

抛物线绘制的主要要点是对抛物线运动过程的理解,以及抛物线绘制结果与被抛物体运动轨迹统一的问题。只要想清楚这两点,实现起来就是分分钟的事情拉。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享