[Day9] Vite 出小蜜蜂~撞击行为 Collision Behavior!

Day9

Collision Behavior

LaserSquid 相互撞击时,
我们想要将 Squid 从场上移除。
我们需要一个 event 让我们得知发生撞击,并且需要做什麽事情。

新增一个 collision 参数,
当开始发生撞击时, start 函式会被调用,并传入当前撞击的物件。

export interface Collision {
  collider: {
    size: Vector;
  };

  collision?: {
    start?<T extends GameObject & Collision>(this: T, collider: T): void;
  };
}

当撞击发生时执行 start 函式,

note
我们希望 start 函式的 this 指向 GameObject 本身而非元件,
故使用 call 并传入物件作为 this

export function collisionDetect(instances: (Collision & Transform)[]) {
  for (let i = 0; i < instances.length; i++) {
    for (let j = i + 1; j < instances.length; j++) {
      const A = instances[i];
      const B = instances[j];

      const o1 = {
        x: A.position.x,
        y: A.position.y,
        w: A.collider.size.x,
        h: A.collider.size.y,
      };
      const o2 = {
        x: B.position.x,
        y: B.position.y,
        w: B.collider.size.x,
        h: B.collider.size.y,
      };

      if (hitTest(o1, o2)) {
+       A.collision?.start?.call(A, B);
+       B.collision?.start?.call(B, A);
      }
    }
  }
}

我们需要实作一个机制,让系统知道我们要销毁某个物件。
destroy 被设置成 true 时,
我们就要将该物件移除。

export interface GameObject {
  destroy?: boolean;
  update?(delta: number): void;
}
export default function Game(screen: Rectangle): Scene<Container> {
  let instances: GameObject[] = [LaserCannon(screen), Squid()];

  return {
    update(delta) {
      collisionDetect(instances.filter(canCollision).filter(canTransform));

      instances.forEach((instance) => {
        if (canControl(instance)) {
          instance.handleInput(getKeyPressed());
        }

        if (canShoot(instance) && instance.canShoot) {
          requestAnimationFrame(() => {
            instances = [...instances, instance.shoot()];
          });

          instance.canShoot = false;
        }

+       if (instance.destroy) {
+         requestAnimationFrame(() => {
+           instances = instances.filter((_instance) => _instance !== instance);
+         });

+         return;
+       }

        instance.update?.(delta);
      });
    },

    render(stage) {
      instances
        .filter(canRender)
        .forEach((instance) => render(stage, instance));
    },
  };
}

Laser 撞到其他物件时,就将 Laser 自己跟撞击到的物件移除。

function Laser({
  x,
  y,
}: Vector): GameObject & Transform & Renderer & Collision {
  return {
    renderer: {
      type: "graphics",
      src: [[1], [1], [1], [1]],
    },

    position: { x, y },

    update() {
      this.position.y -= 1;
    },

    collider: {
      size: { x: 1, y: 4 },
    },

    collision: {
      start(other) {
        other.destroy = true;
        this.destroy = true;
      },
    },
  };
}

关於兔兔们:


<<:  30天轻松学会unity自制游戏-敌机反击

>>:  用爬虫下载图片

Day11【Web】网路攻击:XSS

XSS 全称为 Cross-site scripting 中文为「跨站脚本攻击」。 通常是指利用网页...

[Day01] 前言

参赛动机 笔者正在转职前端工程师的路上,过去一直知道有铁人赛,也有参加的念头,但由於本人的惰性及害怕...

Android Studio初学笔记-Day1 -大纲介绍

这是我第一次参加这种撰写文章的比赛,参加这个比赛主要是让我能保持学习并透过写文章分享自己的学习历程,...

Day12 Select

Select vs Switch select与switch都是透过case的方式来处理,但两者却大...

TypeScript 能手养成之旅 Day 6 物件型别-基础物件型别

前言 今天要来介绍物件型别里面的基础物件,或许会想说那除了基础物件型别以外,不是还有 TypeScr...