[学习笔记]cocos creator 3.0,实现飞行射击游戏的激光鞭(二)

三、代码实现逻辑

3.1 普通子弹

        此处的普通子弹的作用有两个,提供坐标给Line组件绘制激光,与敌机产生碰撞。

        普通子弹的运行较为简单,因为教程很多,不赘述了,与普通子弹不同是,需要添加一个boolean值,用于判断子弹是否已经销毁,因为如果销毁了,就不再用其坐标绘制激光。

3.2 子弹控制器

       因为子弹的密度越高,激光会越平滑,所以需要设定一下子弹的数量上限,达到上限后的子弹自动销毁,优化一部分性能。

        初始化的子弹节点存入数组bulletNodes,子弹数量达到上限后,销毁最早发射的子弹,并把最近生成的子弹存入数组。


                if (self.bulletNodes.length < self.maxPointNum) {
                    newBulletNode.getComponent(BulletByUpdate)?.init(
                        BulletDirection.TO_UP,  //子弹朝向
                        self.oriPos,            //子弹发射坐标
                        self.distance,          //子弹移动距离
                        self.speed,             //子弹速度
                        90,                     //子弹角度
                        self.bulletSprite,      //子弹的精灵
                        BulletExplodeAnimation.NONE     //子弹爆炸 动画
                    )
                    self.bulletNodes.push(newBulletNode);
                    find("Canvas/BulletLayer")!.addChild(newBulletNode);
                }

                else
                {
                    self.bulletNodes.push(newBulletNode);
                    self.bulletNodes[0].destroy();
                    self.bulletNodes.shift();

                    self.bulletNodes[self.bulletNodes.length - 1].getComponent(BulletByUpdate)?.init(
                        BulletDirection.TO_UP,
                        self.oriPos,
                        self.distance,
                        self.speed,
                        90,
                        self.bulletSprite,
                        BulletExplodeAnimation.NONE
                    )
                    find("Canvas/BulletLayer")!.addChild(self.bulletNodes[self.bulletNodes.length - 1]);
                }

3.3 Line组件绘制激光

        有了bulletNodes后就可以每帧遍历数组内的子弹坐标绘制激光了,此时需要处理第一个问题,如下图:

        当敌机从侧面碰撞子弹后(碰撞了橙色点的子弹),此时绿色点的子弹并未消失,Line的绘制仍会将绿色点和蓝色点连接起来,造成激光穿过敌机的现象,此时应该在update里,每帧获取子弹的碰撞状态,并通过计算仅在bulletNodes数组内保留蓝色的子弹节点。

        let i = 0;
        let destroyNodes;
        for (i = 0; i < this.bulletNodes.length; i++) {
            if (this.bulletNodes[i].position != null && this.bulletNodes[i].position != undefined) {
                if (this.bulletNodes[i].getComponent(BulletLaserByUpdate)?.hasCrash()) {
                    // console.log("i:" + i);
                    destroyNodes = this.bulletNodes.splice(0, i);   //获取撞击的拐点,并将其之前的拐点全部删除
                    let j = 0;
                    for (j = 0; j < destroyNodes.length; j++) {
                        destroyNodes[j].destroy();      //将删除的拐点全部销毁
                    }
                }
            }
        }

        然后再遍历bulletNodes,获取坐标,存入数组,用于最后给LINE组件绘制用:

            this.pointVec = new Array<Vec3>();
            let a = 0;
            for(a = 0;a<this.bulletNodes.length;a++)
            {
                if(this.bulletNodes[a].active != false)
                {
                    this.pointVec.push(this.bulletNodes[a].getWorldPosition());
                }

            }

        之后还需要处理第二个问题,因为每个子弹发射有一定的时间间隔,在下一发子弹未出现前,激光的两端以第一颗和最后一颗子弹为拐点,那在最新一发子弹发出前后,LINE组件分别如下图绘制:

        这样会导致激光发射位置持续反复横跳,看着很不舒服,所以此时需要设置一个固定的起始点作为Line组件的发射点。

            let planeHead: Vec3 = null!;
            //如果未定义子弹的初始发射位置,则把发射初始位置设置在预制体前部中间位置
            if (this.shotPos != null && this.shotPos != undefined) {
                planeHead = new Vec3(this.fatherNode.worldPosition.x + this.shotPos.x,
                    this.fatherNode.worldPosition.x + this.shotPos.y,
                    0)
            }
            else if (this.shotPos == null) {
                if (this.direction == BulletDirection.TO_UP) {
                    planeHead = new Vec3(this.fatherNode.getWorldPosition().x,
                        this.fatherNode.getWorldPosition().y
                        + this.fatherNode.getComponent(UITransform)?.height! / 2);
                }
                else if (this.direction == BulletDirection.TO_DOWN) {
                    planeHead = new Vec3(this.fatherNode.getWorldPosition().x,
                        this.fatherNode.getWorldPosition().y
                        - this.fatherNode.getComponent(UITransform)?.height! / 2);
                }
            }
    
            this.pointVec.push(planeHead);

 最后为Line组件设置拐点:

            this.laserLine.positions = this.pointVec as never;

就完成了。

四、效果显示优化。

        因为Line只是单纯的一条直线,可以通过粒子效果分别在激光头尾部挂载,实现看起来比较酷炫的效果。

        效果如下:

        配置如下:

         PositionType需要设置成RELATIVE效果。

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值