JavaScript»ゲーム制作»clickイベント トランプをめくる(一枚)

ファイル名: js-game/quest_00727.html

下のプログラムをうつして、クリックされたトランプカードがおもてを向くようにしてください。画像がぞうは下のリンクからダウンロードできます。

画像をダウンロード

ソースコード

class Card {

  constructor(image, num, mark, x, y) {
    this.image = image;
    this.num = num;
    this.mark = mark;
    this.x = x;
    this.y = y;
    this.opened = false; // 最初は裏向き
  }

  contains(x, y) {
    return x > this.x && x < this.x + 32 && y > this.y && y < this.y + 64;
  }

  open() {
    this.opened = true;
  }

  update() {
    // 特に自動的に変化するデータはない
  }

  render(context) {
    const trimX = this.opened ? this.num * 32 : 448;
    const trimY = this.opened ? this.mark * 64 : 128;
    context.drawImage(this.image, trimX, trimY, 32, 64, this.x, this.y, 32, 64);
  }
}

const canvas = document.getElementById("canvas");
const context = canvas.getContext("2d");

const image = new Image();
image.src = "cards.png";
image.addEventListener("load", () => {

  const num = Math.floor(Math.random() * 13);
  const mark = Math.floor(Math.random() * 4);  
  const card = new Card(image, num, mark, 144, 128);

  canvas.addEventListener("click", (e) => {
    const rect = e.target.getBoundingClientRect();
    const x = e.clientX - rect.left - 1;
    const y = e.clientY - rect.top - 1;
    if (card.contains(x, y)) {
      card.open();
    }
  });

  const FPS = 20;
  const frameTime = 1 / FPS;
  let prevTimestamp = 0;

  const update = (timestamp) => {

    const elapsed = (timestamp - prevTimestamp) / 1000;
    if (elapsed <= frameTime) {
      requestAnimationFrame(update);
      return;
    }

    prevTimestamp = timestamp;

    card.update();
    context.clearRect(0, 0, 320, 320);
    card.render(context);
    requestAnimationFrame(update);
  };

  update();
});

解説

Cardクラスのメソッドの働きを簡単に説明すると、

  • contains:引数の座標が範囲内ならtrueを、そうでなければfalseを返す
  • open:openedプロパティの状態をtrue(表)にする
  • update:なにもしません
  • render:openedの状態が裏か表かによって画像の切り出す部分を決め、表示する
  • ページが読み込まれたとき(loadイベント)、ランダムにトランプの数字とマークを決めて、クラスからcardオブジェクトを作ります。(36~40行目)

    クリックしたとき、クリックされた点のキャンバス上の座標を計算し、カードの上ならcontainsメソッドがtrueを返しopenメソッドが実行されます。(42~49行目)

    20フレームごとにキャンバスの画像は更新され、今の状態が反映されます。(51~71行目)