Collision detection with Canvas

by bc_rikko

HTML

<div>
  <canvas id="app" width="640" height="360"></canvas>
</div>
<button id="start">start</button>
<button id="stop">stop</button>

CSS

canvas {
  background-color: white;
}

JavaScript

class Game {
  constructor(opt) {
    this._canvas = opt.canvas;
    this._ctx = this._canvas.getContext('2d');
    
    this._assets = opt.assets;
    this._loadedAssets = {};
    
    this._fps = opt.fps || 30;
    this._timer;
    this._items = [];
    this._keyboard = '';
    this._setEventListener();

    // 当たり判定用リスト
    this.hitTests = [];
  }

  /**
   * 当たり判定を追加する
   * @param {Object} opt オプション
   * @param {Object} opt.self 主のオブジェクト
   * @param {Object} opt.target 当たり判定の対象
   * @param {Function} opt.onhit 衝突検知したときの処理
   */
  addHitTest(opt) {
    this.hitTests.push(opt);
  }
  /**
   * 当たり判定を削除する
   * @param {Object} opt オプション
   * @param {Object} opt.self 主のオブジェクト
   * @param {Object} opt.target 当たり判定の対象
   * @param {Function} opt.onhit 衝突検知したときの処理
   */
  removeHitTest(opt) {
    const index = this.hitTests.findIndex(a => a === opt);
    this.hitTests.splice(index, 1);
  }
  /**
   * 当たり判定を行う
   * @param {Object} self メイン
   * @param {Object} target ターゲット
   * @return {boolean} 衝突検知したらtrue
   */
  _hitTest(self, target) {
    const myTop = self.y;
    const myBottom = self.y + self.h;
    const myLeft = self.x;
    const myRight = self.x + self.w;

    const targetTop = target.y;
    const targetBottom = target.y + target.h;
    const targetLeft = target.x;
    const targetRight = target.x + target.w;

    return (myTop < targetBottom && targetTop < myBottom) && (myLeft < targetRight && targetLeft < myRight);
  }

  //以下の詳細は参照→ http://kuroeveryday.blogspot.jp/2017/10/canvas-how-to-move-object-with-keyboard.html
  // _renderのみ修正
  async start() {
    await this._loadAssets();
    this._timer = setInterval(() => {
      this._render();
    }, 1000 / this._fps);
  }
  stop() {
    clearInterval(this._timer);
  }
  async _loadAssets() {
    const promises = Object.keys(this._assets).map(asset => {
      return new Promise((resolve, reject) => {
        const img = new Image();
        img.onload = () => { resolve(); }
        img.onerror = err => {...