特效就是在碰撞点画一个半径不断增大的园,当园的半径到一定值的是消失,这里我们可以通过半径与透明度成反比实现,即const alpha = 1 - (this.radius[i] / 80)。画圆通过 arc 函数实现。

    创建 save.ts ,记得在 init 初始化和导出它。

    这里的 type 字段是为了记录碰撞类型,默认与果实碰撞是 false,与小鱼碰撞是 true,根据不同的类型,使用不同的画笔样式

    1. import { ctx_one } from "./init";
    2. import { deltaTime } from "./game-loop";
    3. class Wave {
    4. x: number[] = [];
    5. y: number[] = [];
    6. alive: boolean[] = [];
    7. radius: number[] = []
    8. type: boolean[] = [];
    9. num = 20 // 定义10个 wave 等待使用
    10. constructor() {
    11. for (let i = this.num; i >= 0; i-- ) {
    12. this.alive[i] = false
    13. this.type[i] = false;
    14. this.radius[i] = 0;
    15. }
    16. }
    17. draw(){
    18. for (let i = this.num; i >= 0; i--) {
    19. if(this.alive[i]) { // 假如是的存活,开始绘制一个逐渐变大的 ○
    20. if(this.radius[i] > 50) { // 假如半径大于 50 让它死亡
    21. this. alive[i] = false
    22. continue;
    23. }
    24. ctx_one.save()
    25. ctx_one.shadowBlur = 5;
    26. ctx_one.shadowColor = 'white';
    27. ctx_one.lineWidth = 5;
    28. if(this.type[i]) { // true 代表小鱼与大鱼碰撞
    29. this.radius[i] += deltaTime * 0.04;
    30. const alpha = 1 - (this.radius[i] / 80)
    31. ctx_one.strokeStyle = `rgba(203,91,0,${alpha})`
    32. }else{
    33. this.radius[i] += deltaTime * 0.05;
    34. const alpha = 1 - (this.radius[i] / 50)
    35. ctx_one.strokeStyle = `rgba(255,255,255,${alpha})`
    36. }
    37. ctx_one.beginPath()
    38. ctx_one.arc(this.x[i], this.y[i], this.radius[i], 0, 2 * Math.PI)
    39. ctx_one.closePath()
    40. ctx_one.stroke()
    41. ctx_one.restore()
    42. }
    43. }
    44. }
    45. born(x: number,y: number, type = false){
    46. for (let i = this.num; i >= 0; i--) {
    47. // 找到第一个没有存活的,让他复活。
    48. if (!this.alive[i]) {
    49. this.alive[i] = true // 存活代表显示出来
    50. this.radius[i] = 20;
    51. this.x[i] = x;
    52. this.y[i] = y;
    53. this.type[i] = type // 设置类型为 true; 当为 true 的时候,代表鱼妈妈与鱼宝宝碰撞
    54. return ;
    55. }
    56. }
    57. }
    58. }
    59. export default Wave;

    之后在碰撞逻辑里面调用 born

    1. // 假如距离小于 900 就喂食给 baby,且必须要鱼妈妈吃到了果实才能喂给小鱼
    2. if (distance < 900 && score.fruitNum != 0) {
    3. fish_baby.recover();
    4. // 把能力给小鱼,果实数清零,计算分数一次
    5. score.reset()
    6. // 把大鱼的 bodyindex 恢复成 0
    7. fish_mother.BodyIndex = 0;
    8. wave.born(fish_baby.x, fish_baby.y, true) // 出生一个波浪
    9. }
    1. // 假如距离小于 500 让果实死亡
    2. if(distance < 500) {
    3. fruits.dead(i)
    4. score.fruitNum++; // 计分系统的果实数加一
    5. if(fruits.fruitType[i] === FruitType.Blue) { // 假如吃到蓝色道具果实,开启双倍模式
    6. score.doubleMode = 2;
    7. }
    8. // 把鱼儿吃掉果实的位置传过去,(传鱼的坐标或者果实坐标都可以)
    9. wave.born(fruits.x[i], fruits.y[i])
    10. }

    最后别忘记在 gameLoop 里面调用 draw 函数。

    1. score.draw() // 绘制分数
    2. wave.draw()