最近,有小伙伴在后台留言,让我赶紧更新帧同步。这几天因为有其他事情,所以一直没更新。
于是乎,周末这两天,赶紧撸起代码来,把子弹的同步和碰撞检测加了上去。好友拉我开黑都把他无情的拒绝了。
先说下我的思路吧。原本,我想着战斗时,右摇杆点击之后就一直发射子弹,间隔0.2秒发射一次,只要控制方向就可以了。但是,通过schedule和interval实现之后,发现效果不是太理想。然后,我又改造了一下interval,想实现类似于引擎的update驱动那样,然后通过手动累加时间,每到0.2秒就触发一次发射,写完之后,感觉效果倒是还可以。但是,到真机上测试,不知道为什么,真机上不显示连续发射的子弹。
于是,最终我放弃了这种方式。改为每次松开摇杆时,发射一颗子弹。我之前玩过一款对战小游戏就是这样做的,不过是,我这没有加瞄准线,这个后期可以再加。效果视频如下。(interval实现的代码被我注释了,以后再研究)
然后说下,子弹同步的思想。逻辑层每个玩家类下都维护了一个子弹类的数组,然后每一帧计算出所有子弹的位置信息。表现层,也维护了一个子弹类的数组用于和逻辑层一一对应。
需要注意的是,两个数组的顺序一定要包管一致,不然子弹会错乱。这个实现方法,是在逻辑层把需要销毁的子弹先delete,也就是子弹对象置为undefined,这样不会改变数组的长度,然后在表现层再同步删除子弹数组中所有undefined的对象。
子弹的位置,是以地图map节点为父节点计算出来的位置。因为,玩家的坦克父节点也是map,这样计算碰撞时比较方便。但是,需要注意的是,逻辑层是在每一帧时计算的位置,子弹位置和坦克位置之间是有偏移量的。由于坦克位置是不连续的,因此子弹位置也是不连续的。所以,不能在表现层直接设置子弹位置,因为,表现层的坦克位置是插值来的。因此,需要在表现层用当前插值后的坦克位置加上这个偏移量。代码在Hero.ts的copyBullets方法下。
表现层所有子弹都是只给初始位置,然后通过引擎update自动计算每个子弹的后续位置。因为,我发现如果用插值计算子弹位置,子弹前进过程中会一卡一卡的。
关于碰撞检测,需要在逻辑层维护一个坦克和子弹的大小,即宽高。然后遍历所有敌方未死亡的坦克,判断子弹是否和敌方坦克相交。
刚开始我是在逻辑层做计算,检测到碰撞之后,在表现层同步的删除子弹对象,然后把子弹节点也销毁。但是,多次测试发现,画面呈现的是,子弹会提前或者延后销毁。也就是子弹还没走到坦克的位置就已经不见了,或者是子弹已经穿出了坦克还没被销毁。
因此,最后,我在表现层也做了一个碰撞检测。这个只是为了让玩家的画面看起来不会那么奇怪。(明明子弹碰到了敌方坦克,为什么子弹还在。)实际计算伤害时,还是以逻辑层为准。伤害计算后续更新。
代码已经在gitee仓库更新了,小伙伴们可以自行下载。(建议加星,或者建立当地仓库连接,pull代码更方便。)
扫描二维码
获取更多精彩
如若清风
关注公众号,回复666666
即可领取学习大礼包